详解应用层open函数如何调用到底层驱动中xxx_open函数

原文链接

linux中一切皆文件,内核如何来区别每一个文件,这个叫做inode号,每个文件有一个特定的inode号

用ls  -i查看文件inode号,每个文件会对应一个inode结构体,inode结构体的内容非常多,我们省略了一部分

struct inode {
    umode_t i_mode;  // 打开方式
    kuid_t i_uid;  // 用户id
    kgid_t i_gid;  // 组id
    unsigned int i_flags;  // 权限标志位,阻塞,非阻塞... 标志位信息


    const struct inode_operations*i_op;  // inode 操作方法集
    struct super_block*i_sb;
    struct address_space*i_mapping;


    unsigned longi_ino;  // inode 号码
    union {
         const unsigned int i_nlink;
         unsigned int __i_nlink;   // 链接数
    };
    dev_ti_rdev;   // 设备号
    struct timespeci_atime;  // 访问时间
    struct timespeci_mtime;  // 修改时间
    struct timespeci_ctime;   // 创建时间

    // 存储信息
    unsigned short          i_bytes;
    unsigned int i_blkbits;
    blkcnt_t i_blocks;


    const struct file_operations*i_fop; /* 文件操作方法集合 */
    struct list_headi_devices;  // 内核循环双链表节点
    union {
         struct pipe_inode_info*i_pipe;
         struct block_device*i_bdev;
         struct cdev *i_cdev;   // 字符设备对象指针
       };
...
};

        inode结构体包含很多信息,如文件的权限信息,文件的时间信息等等。在驱动文件中,我们主要关注标红的信息,inode号,设备号,文件操作集合。使用mknod创建设备节点时,会将inode号和设备号关联起来。若此时内核中已经注册了该设备号的对象,此时会将设备对象的操作方法集合赋值到此处。

        文件操作集合i_fop指向了def_chr_fops,这个结构中的open函数指向了chrdev_open。chrdev_open完成的主要工作是:首先根据设备号找到添加在内核中代表字符设备的cdev。找到对应的cedv对象后,用cedv关联的操作方法集和赋值给新建的file结构体中的文件操作集合。并调用操作集合中的open函数,完成真正的打开操作。

       一个驱动可能会被多应用打开,那多次打开时是生成多个inode号吗?答案是否定的。inode号是唯一的,那如何表示多次打开一个驱动文件呢?

        系统中每个打开的文件在内核空间都有一个对应的file结构体。

struct file {
struct path f_path;  // 路径名称
struct inode *f_inode; /*inode 指针*/
const struct file_operations *f_op;  // 文件操作集合
unsigned int f_flags;  // 标志位信息
fmode_t f_mode;  // 操作方式
loff_t f_pos;
struct fown_struct f_owner;  // 异步通知 ,需要用到此结构体
void *private_data;
...
};

我们来看看struct file_operations中定义的方法原型,只有在open和release时才会有inode参数,其余的操作都用file结构体来操作文件。也就是在open时会将inode和file结构体关联起来,fil结构体中有inode指针f_inode指向了文件的inode结构体。

我们来看一下下面这副图

猜你喜欢

转载自blog.csdn.net/weixin_42048417/article/details/81155819
今日推荐