字符设备驱动剖析

来源:互联网 发布:游族网络最新消息预测 编辑:程序博客网 时间:2024/05/27 03:30

整体流程

这里写图片描述
这是字符设备里面主要写的函数,我们接下来一个一个分析他们在系统中运作的原理。

字符设备打开过程

这里写图片描述

int fd = open("/dev/demo0", O_RDWR);

^
| 用户空间(3G)
—-系统调用—————————————–
| 内核空间(1G)
V
1、找inode节点,得到设备号
2、根据设备号遍历cdev节点,找到cdev对象
3、创建file对象(数组,其标号就是文件描述符)
4、初始化file对象,把file->f_op指向cdev指向的file_operations //将两个方法集交流
5、回调驱动open函数

struct file {    struct inode        *f_inode;   //对应的inode节点    const struct file_operations    *f_op;  //指向驱动的file_operations    unsigned int        f_flags;    //标志(工作方式):阻塞、异步通知、...    fmode_t         f_mode;     //读写权限:O_RDONLY、...    loff_t          f_pos;      //文件读写位置    void            *private_data;  //私有数据,扩展属性    ...}

从file中提取inode节点
3.5内核

linux/fs.hstruct file {    ...    struct path     f_path;}linux/path.hstruct path {    ...    struct dentry *dentry;};linux/dcache.hstruct dentry {    ...    struct inode *d_inode;}

4.x内核

linux/fs.hstatic inline struct inode *file_inode(const struct file *f){    return f->f_inode;}

字符设备驱动中file_operations登记的函数就像内核的库函数一样,总是被用户层代码调用
当驱动的函数被用户进程调用时候,则其从属于相应的进程空间

int fd = open("/dev/demo0", O_RDWR);    ^    |               用户空间(3G)----系统调用-----------------------------------------    |               内核空间(1G)    V      ......struct file_operations {    ...    int (*open) (struct inode *, struct file *);    ...}

得到进程号:

asm/current.hlinux/sched.h#define current get_current()

得到进程号:current->pid
得到进程名:current->comm

字符设备读写过程

这里以读的过程举例,写的过程类似。
用户层调用函数

ssize_t read(int fd, void *buf, size_t count);

驱动实现的代码

ssize_t xxx_read (struct file *, char __user *, size_t, loff_t *);

驱动的read和用户层的read传入参数很类似,只是用户层函数中有fd,而驱动层有个file*和loff_t*
下面简要介绍一下如何由用户调用函数找到驱动函数。
这里写图片描述
【1】首先使用open打开设备文件,而open返回fd就是设备在VFS中的FILE结构体节点
【2】其实这个节点就是我们写驱动时对应的设备文件
【3】通过FILE结构体节点找到方法集file_operations
【4】调用方法集里面的xxx_read(我们编写的驱动程序 )。

设备节点创建过程

这里写图片描述

设备驱动注册过程

这里写图片描述

0 0