加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux 字符设备——驱动框架(二)

发布时间:2020-12-14 00:37:52 所属栏目:Linux 来源:网络整理
导读:字符设备驱动框架 (前言) 前面编写了一个简单的linux字符设备驱动。接下来简单地来看一下字符设备驱动的框架。 一、重要的数据结构 在linux 字符设备里,有三个比较重要的数据结构,分别是: struct file_operations , struct file 和 struct inode 下面来简

字符设备驱动框架

(前言)

前面编写了一个简单的linux字符设备驱动。接下来简单地来看一下字符设备驱动的框架。

一、重要的数据结构

在linux 字符设备里,有三个比较重要的数据结构,分别是:struct file_operationsstruct filestruct inode
下面来简单的说明一下

1、struct file_operations

这个结构体是相当于设备的驱动了,实现了字符设备的相关操作函数

/* 只介绍部分struct file_operations结构体的成员 */
struct file_operations {
    /* struct module 这个成员不是一个操作; 它是一个指向拥有这个结构体的模块指针。
     * 这个成员用来在它还被使用时阻止模块被卸载。一般初始化为 THIS_MODULE,*/
    struct module *owner;
        
    /* llseek 函数用来改变文件中当前的读/写的位置,如果这个函数指针是NULL,内核中
     * 缺省的实现通过修改filp->f_pos进行移位
     */
    loff_t (*llseek) (struct file *,loff_t,int);

    /* read函数用来从设备中获取数据。如果这个函数指针是NULL,以 -EINVAL 失败返回给
     *  read 系统调用,一个非负返回值代表了成功读取的字节数。
     */
    ssize_t (*read) (struct file *,char __user *,size_t,loff_t *);

    /* write函数用来发送数据给设备。如果这个函数指针是NULL,以 -EINVAL 失败返回给
     *  write 系统调用,一个非负返回值代表了成功读取的字节数。
     */
    ssize_t (*write) (struct file *,const char __user *,loff_t *);

    /* poll 函数是: poll,epoll 和 select 这三个系统调用的后端。这三个系统调用都用作查询对一个
     * 或者多个文件描述符的读或写是否会阻塞。poll函数应返回一个位掩码指示是否非阻塞的读或
     * 者写是可能的。并且给内核提供信息,用来使调用的的进程睡眠,直到读写操作变为可能。
     * 如果一个驱动的 poll 指针为 NULL,设备假定为不阻塞地可读可写。
     */
    unsigned int (*poll) (struct file *,struct poll_table_struct *);

     /* ioctl 函数 为 ioctl() 系统调用提供了发出设备特定命令的方法
      * 如果一个驱动的 ioctl 指针为 NULL,对于任何未事先定义的请
      * 求返回 -ENOTTY,系统调用返回一个错误
      */
    int (*ioctl) (struct inode *,struct file *,unsigned int,unsigned long);

     /* mmap 用来请求将设备内存映射到进程的地址空间,* 如果这个指针是 NULL,mmap 系统调用返回 -ENODEV.
      */
    int (*mmap) (struct file *,struct vm_area_struct *);
     
     /* open成员是 open 系统调用的后端,通常是对设备文件进行的第一个操作
      * 如果这个指针是 NULL,设备打开一直成功,但是你的驱动不会得到通知.
      */
    int (*open) (struct inode *,struct file *);

     /* release成员是 close系统调用的后端,在文件结构被释放时引用这个操作。
      * 如同open,release成员也可以为NULL。
      */
    int (*release) (struct inode *,struct file *);

     /* fasync这个操作用来通知设备它的 FASYNC 标志的改变(异步通知)
      * 如果这个成员是 NULL,驱动不支持异步通知。
      */
    int (*fasync) (int,int);
};

2、struct file

这个结构体描述的是打开的一个文件,每打开一个文件就会有一个struct file结构体来进行管理

/* 只介绍部分struct file结构体的成员 */
struct file {

    /* 文件模式确定文件是可读的或者是可写的(或者都是),*  通过位 FMODE_READ 和FMODE_WRITE 描述
     */
    mode_t          f_mode;

    /*  文件当前的读写位置. 如果驱动需要知到文件中的当前位置,可以读这个值,但是不应该改变它。
     *  在fops 的 read 和 write 以最后的一个参数传入,来代替直接使用f_pos成员,在fops的llseek方法中
     *  通过改变f_pos 成员来改变,文件的读写位置
     */
    loff_t          f_pos;

    /*  文件的标志。例如 O_REONLY,O_NONBLOCK,和 O_SYNC。驱动通过检查O_NONBLOCK标志
     *  来查看是否请求非阻塞操作,其他标志一般比较少用。
     */
    unsigned int        f_flags;

    /* 和文件关联的操作*/
    const struct file_operations    *f_op;

    /* 这个成员通常用来指向分配的数据,通常在fops->open 成员函数里面指定。
     * 如果使用了这个成员必须在fops->release 成员中释放。
     */
    void            *private_data;
};

3、struct inode

inode 结构用来描述磁盘上一个文件。inode 结构包含大量关于文件的信息,但这个结构只有 2 个成员对于编写驱动代码有用

/* 只介绍部分struct inode结构体的成员 */
struct inode {
    /* 对于代表设备文件的节点,这个成员包含实际的设备编号. */
    dev_t    i_rdev;
    union {
        struct pipe_inode_info  *i_pipe;
        /* 当节点指的是一个块设备文件时,代表块设备。*/
        struct block_device     *i_bdev;
        /* 当节点指的是一个字符设备文件时,代表字符设备。*/
        struct cdev             *i_cdev;
    };
}

二、linux 源代码框架分析

系统调用的到内核驱动的调用过程如下(以 open 系统调用为例,其他的系统调用类似)
(系统调用的入口函数在 kernel/calls.S 这个文件里面)
??sys_open
???? do_sys_open
?????? fd = get_unused_fd(); //找到一个本进程没有使用的文件描述符
?????? struct file *f = do_filp_open(dfd,tmp,flags,mode); // 构造和设置struct file 结构体
???????? nameidata_to_filp(&nd,flags);
?????????? __dentry_open(nd->dentry,nd->mnt,filp,NULL);
???????????? if (!open && f->f_op)//open是一个函数指针作为__dentry_open 的第五个参数
?????????????? open = f->f_op->open; //获取fops的open成员
???????????? if (open) {
?????????????? error = open(inode,f); //调用函数open函数
???????????? }

三、框架图

<念念有余>这位博主有一张比较详细的框架图,所以直接引用过来了

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读