美文网首页
kernel1- 驱动open 流程

kernel1- 驱动open 流程

作者: xuefeng_apple | 来源:发表于2020-10-21 11:51 被阅读0次
    open 流程

    inode --->cdev--->cdev_map--->file_ops
    cdev_map: 是要在驱动注册的时候,创建了cdev,然后加入cdev_map , open是由根据inode 中的i_cdev 进行驱动程序的寻找

    文件对应唯一一个inode, 不管Open 几次,软连接几次。
    struct inode

    struct inode {
        umode_t         i_mode;//文件的访问权限(eg:rwxrwxrwx)
        unsigned short      i_opflags;
        kuid_t          i_uid;//inode拥有者id
        kgid_t          i_gid;//inode拥有者组id
        unsigned int        i_flags;//inode标志,可以是S_SYNC,S_NOATIME,S_DIRSYNC等
    
    #ifdef CONFIG_FS_POSIX_ACL
        struct posix_acl    *i_acl;
        struct posix_acl    *i_default_acl;
    #endif
    
        const struct inode_operations   *i_op;//inode操作
        struct super_block  *i_sb;//所属的超级快
        /*
            address_space并不代表某个地址空间,而是用于描述页高速缓存中的页面的一个文件对应一个address_space,一个address_space与一个偏移量能够确定一个一个也高速缓存中的页面。i_mapping通常指向i_data,不过两者是有区别的,i_mapping表示应该向谁请求页面,i_data表示被改inode读写的页面。
        */
        struct address_space    *i_mapping;
    
    #ifdef CONFIG_SECURITY
        void            *i_security;
    #endif
    
        /* Stat data, not accessed from path walking */
        unsigned long       i_ino;//inode号
        /*
         * Filesystems may only read i_nlink directly.  They shall use the
         * following functions for modification:
         *
         *    (set|clear|inc|drop)_nlink
         *    inode_(inc|dec)_link_count
         */
        union {
            const unsigned int i_nlink;//硬链接个数
            unsigned int __i_nlink;
        };
        dev_t           i_rdev;//如果inode代表设备,i_rdev表示该设备的设备号
        loff_t          i_size;//文件大小
        struct timespec     i_atime;//最近一次访问文件的时间
        struct timespec     i_mtime;//最近一次修改文件的时间
        struct timespec     i_ctime;//最近一次修改inode的时间
        spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */
        unsigned short          i_bytes;//文件中位于最后一个块的字节数
        unsigned int        i_blkbits;//以bit为单位的块的大小
        blkcnt_t        i_blocks;//文件使用块的数目
    
    #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t      i_size_seqcount;//对i_size进行串行计数
    #endif
    
        /* Misc */
        unsigned long       i_state;//inode状态,可以是I_NEW,I_LOCK,I_FREEING等
        struct mutex        i_mutex;//保护inode的互斥锁
    
        //inode第一次为脏的时间 以jiffies为单位
        unsigned long       dirtied_when;   /* jiffies of first dirtying */
    
        struct hlist_node   i_hash;//散列表
        struct list_head    i_wb_list;  /* backing dev IO list */
        struct list_head    i_lru;      /* inode LRU list */
        struct list_head    i_sb_list;//超级块链表
        union {
            struct hlist_head   i_dentry;//所有引用该inode的目录项形成的链表
            struct rcu_head     i_rcu;
        };
        u64         i_version;//版本号 inode每次修改后递增
        atomic_t        i_count;//引用计数
        atomic_t        i_dio_count;
        atomic_t        i_writecount;//记录有多少个进程以可写的方式打开此文件
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */ 这里对应是node 的
        struct file_lock    *i_flock;//文件锁链表
        struct address_space    i_data;
    #ifdef CONFIG_QUOTA
        struct dquot        *i_dquot[MAXQUOTAS];//inode磁盘限额
    #endif
        /*
            公用同一个驱动的设备形成链表,比如字符设备,在open时,会根据i_rdev字段查找相应的驱动程序,并使i_cdev字段指向找到的cdev,然后inode添加到struct cdev中的list字段形成的链表中
        */
        struct list_head    i_devices;,
        union {
            struct pipe_inode_info  *i_pipe;//如果文件是一个管道则使用i_pipe
            struct block_device *i_bdev;//如果文件是一个块设备则使用i_bdev
            struct cdev     *i_cdev;//如果文件是一个字符设备这使用i_cdev
        };
    
        __u32           i_generation;
    
    #ifdef CONFIG_FSNOTIFY
       //目录通知事件掩码
        __u32           i_fsnotify_mask; /* all events this inode cares about */
        struct hlist_head   i_fsnotify_marks;
    #endif
    
    #ifdef CONFIG_IMA
        atomic_t        i_readcount; /* struct files open RO */
    #endif
        //存储文件系统或者设备的私有信息
        void            *i_private; /* fs or device private pointer */
    };
    

    struct file

     struct file {
            struct list_head        f_list;
            struct file_operations  *f_op;  ---》对应了驱动的写的read ,write..函数
            mode_t                  f_mode;
            struct fown_struct      f_owner;
            unsigned int            f_uid, f_gid;
     };
    
    

    file_operation就是把系统调用和驱动程序关联起来的关键数据结构
    struct file_operation 驱动中

    struct file_operations {
      struct module *owner;
      loff_t(*llseek) (struct file *, loff_t, int);
      ssize_t(*read) (struct file *, char __user *, size_t, loff_t *);
      ssize_t(*write) (struct file *, const char __user *, size_t, loff_t *);
      int (*readdir) (struct file *, void *, filldir_t)
      unsigned int (*poll) (struct file *, struct poll_table_struct *);
      int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
      int (*mmap) (struct file *, struct vm_area_struct *);
      int (*open) (struct inode *, struct file *);
      int (*flush) (struct file *);
      int (*release) (struct inode *, struct file *);
      int (*fasync) (int, struct file *, int);
      int (*lock) (struct file *, int, struct file_lock *);
      unsigned long (*get_unmapped_area) (struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    };
    

    linux/include/linux/cdev.h
    struct cdev {
    struct kobject kobj; // 每个cdev 都是一个 kobject
    struct module *owner; // 指向实现驱动的模块
    const struct file_operations *ops; // 操纵这个字符设备文件的方法
    struct list_head list; // 与cdev 对应的字符设备文件的 inode->i_devices 的链表头
    dev_t dev; // 起始设备编号
    unsigned int count; // 设备范围号大小
    };

    int cdev_add(struct cdev *p, dev_t dev, unsignedcount)
    {
    p->dev = dev;
    p->count = count;
    return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
    }
    

    关于 kobj_map() 函数就不展开了,我只是大致讲一下它的原理。内核中所有都字符设备都会记录在一个 kobj_map 结构的 cdev_map 变量中。这个结构的变量中包含一个散列表用来快速存取所有的对象。 kobj_map() 函数就是用来把字符设备编号和 cdev 结构变量一起保存到 cdev_map 这个散列表里。当后续要打开一个字符设备文件时,通过调用 kobj_lookup() 函数,根据设备编号就可以找到 cdev 结构变量,从而取出其中的 ops 字段。

    相关文章

      网友评论

          本文标题:kernel1- 驱动open 流程

          本文链接:https://www.haomeiwen.com/subject/wxbsmktx.html