一、linux系统将设备分为3类:字符设备、块设备、网络设备。

  • 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据。字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等。
  • 块设备:是指可以从设备的任意位置读取一定长度数据的设备。块设备包括硬盘、磁盘、U盘和SD卡等。
  • 网络设备是计算机体系结构中必不可少的一部分,处理器如果想与外界通信,通常都会选择网络设备作为通信接口。众所周知,在 OSI(Open Systems
    Interconnection,开放网际互连)中,网络被划分为七个层次,从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。我们所讲的网络设备也包括两个层次,一层叫做
    MAC(Media Access Control)层,对应于 OSI 的数据链路层;另一层叫做 PHY(Physical Layer)层,对应于物理层。

1.cdev结构体

struct cdev{

  struct kobject kobj;//内嵌的kobj对象

  struct module *owner;//所属模块

  struct file_operations *ops;//文件操作结构体

  struct list_head list;

  dev_t dev;//设备号

  unsigned int count;

};

cdev 结构体的dev_t成员定义了设备号,为32位,其中高12位为主设备号,低20位为次设备号.

MAJOR(dev_t dev)获得主设备号和MINOR(dev_t dev)获得次设备号

MKDEV(int major,int minor)可以生成dev_t

file_operation定义了字符设备提供给文件系统的接口函数

void cedv_init (struct cdev *,struct file_operation *);//初始化cedv的成员,建立cedv和file_operation的连接

struct cdev *cdev_alloc(void);//动态申请一个cdev内存

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned);
void cdev_del(struct cdev *);
 
//cdev_add()函数和 cdev_del()函数分别向系统添加和删除一个 cdev, 完成字符设备的注册和注销

cdev_add()向系统注册字符设备时,先调用register_chrdev_region()或者alloc_chrdev_region()向系统申请设备号

cdev_del()向系统注销字符设备后,unregister_chrdev_region()应该被调用以释放原先申请的设备号

分配和释放设备号

int register_chrdev_region(dev_t from,unsigned count,const char* name);//用已知的设备号

int alloc_chrdev_region(dev_t *dev ,unsigned baseminor,unsigned count,const char *name);//用于设备号未知

void unregister_chrdev_region(dev_t from,unsigned count);//卸载

file_operations结构体

struct file_operation{

struct module *owner;//拥有该模块的指针,一般为this module

loff_t(*llseek)(struct file *,loff_t ,int ,);//用来修改文件的当前位置,并将位置返回,出错返回负值

ssize_t(*read)(struct file * ,char user *,size_t,loff_t);//同步读取,成功返回内容,失败负值

ssize_t(*aio_read)(struct kiocb *,char user *,size_t ,loff_t);//异步读取

ssize_t(*write)(struct file * ,char user *,size_t,loff_t);//同步写入,成功写入内容,失败负值

int(*readdir)(struct file *,void *,filldir_t);//读取目录,对于设备文件,该字段为空,设备节点不需要实现它

unsigned int(*poll)(struct file *,struct poll_table_struct*);//轮询函数,是否为非阻塞的读入还是写出,当询问条件未触发时,select()和poll()系统调用引起阻塞
int(*ioctl)(struct inode *,struct file *,unsigned long);//执行io控制命令
 long(*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
    // 不使用 BLK 文件系统,将使用此种函数指针代替 ioctl
    long(*compat_ioctl)(struct file *, unsigned int, unsigned long);
    // 在 64 位系统上,32 位的 ioctl 调用将使用此函数指针代替
    int(*mmap)(struct file *, struct vm_area_struct*);
    // 用于请求将设备内存映射到进程地址空间,如果设备驱动未实现此函数,用户进行 mmap()系统调用时将获得-ENODEV 返回值
    int(*open)(struct inode *, struct file*);
    // 打开,驱动程序可以不实现这个函数,在这种情况下,设备的打开操作永远成功。
    int(*flush)(struct file*);
    int(*release)(struct inode *, struct file*);
    // 关闭
    int(*synch)(struct file *, struct dentry *, int datasync);
    // 刷新待处理的数据
    int(*aio_fsync)(struct kiocb *, int datasync);
    // 异步 fsync
    int(*fasync)(int, struct file *, int);
    // 通知设备 FASYNC 标志发生变化
    int(*lock)(struct file *, int, struct file_lock*);
    ssize_t(*readv)(struct file *, const struct iovec *, unsigned long,loff_t*);
    ssize_t(*writev)(struct file *, const struct iovec *, unsigned long,loff_t*);
    // readv 和 writev:分散/聚集型的读写操作
    ssize_t(*sendfile)(struct file *, loff_t *, size_t, read_actor_t,void*);
    // 通常为 NULL
    ssize_t(*sendpage)(struct file *, struct page *, int, size_t,loff_t *, int);
    // 通常为 NULL
    unsigned long(*get_unmapped_area)(struct file *,unsigned long,unsigned long,unsigned long, unsigned long);
    // 在进程地址空间找到一个将底层设备中的内存段映射的位置
    int(*check_flags)(int);
    // 允许模块检查传递给 fcntl(F_SETEL...)调用的标志
    int(*dir_notify)(struct file *filp, unsigned long arg);
    // 仅对文件系统有效,驱动程序不必实现
    int(*flock)(struct file *, int, struct file_lock*);
};

unsigned  long copy_from_user(void *to,const void User *from,unsigned long count);

unsigned long copy_to_user(void user* to,const void *from,unsigned count );

//user是一个宏,表明其后的指针指向用户空间

get_user(val,(int *)arg);//用户空间到内核空间,arg是用户空间的地址

put_user(val,(int *)arg);////内核空间到用户空间,arg 是用户空间的地址

Linux字符设备的更多相关文章

  1. 深入理解Linux字符设备驱动

    文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...

  2. Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】

    本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...

  3. Smart210学习记录----beep linux字符设备驱动

    今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...

  4. Linux字符设备中的两个重要结构体(file、inode)

    对于Linux系统中,一般字符设备和驱动之间的函数调用关系如下图所示 上图描述了用户空间应用程序通过系统调用来调用程序的过程.一般而言在驱动程序的设计中,会关系 struct file 和 struc ...

  5. Linux字符设备驱动实现

    Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...

  6. Linux字符设备简单示例

    1. Linux字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现open.close.read和write系统调用.例如:串口.Led.按键等. 2. 通过字符设备文件 ...

  7. Linux字符设备驱动基本结构

    1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...

  8. (57)Linux驱动开发之三Linux字符设备驱动

    1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...

  9. Linux字符设备驱动框架

    字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...

  10. linux 字符设备驱动写法

    字符设备,块设备书 一.register_chrdev_region, register_chrdev, misc_register misc device(杂项设备) 在 Linux 内核的incl ...

随机推荐

  1. function 类型

    一.函数的声明方式 1.普通的函数声明 function box(num1,num2){ return num1+num2; }alert(box(1,2)); 2.使用变量初始化函数 var box ...

  2. 夺命雷公狗-----React---8--react官方提供的组建实现双向绑定

    首先要引入她.. <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  3. Together

  4. 解决jQuery ajax跨域问题,Google、IE、Firefox亲测有效

    直接上最后的结果吧 JS: $.ajax({ type: "GET", async: false, crossDomain: true, url: "www.test.c ...

  5. QT开发实战精解

    无法打开包括文件<QApplication> No such file or directory  这一问题 解决办法,使用QApplication时必须在项目pro文件中添加一句 QT ...

  6. windows 中 使用MongoDB

    MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式. 传统的关系数据库一般由 ...

  7. PHP 回调、匿名函数和闭包

    <?php class Product{ public $name; public $price; function __construct($name, $price){ $this-> ...

  8. 微信 xml 转 Map

    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; xml + ...

  9. 微信小程序配置文件

    app.json   配置文件中不能有注释 { "pages": [ // 必填 设置页面路径 "pages/index/index", "pages ...

  10. 忙了好一阵,今天随便写篇关于canvas的小东西

    前几天在朋友圈发了几条3D demo视频,其中就有3D空间组成各种图形.如上! 那么这些图形的每个mesh的坐标可不是手动去写,如果你愿意我当然不拦着!所以今天这篇就来介绍如何获得这些图形的坐标数据. ...