• Linux设备驱动程序 之 重要数据结构


    文件对象

    文件对象是进程已经打开文件描述符的内存中的表示,单个文件可能有多个表示打开文件描述符的file结构;

     1 struct file {
     2     union {
     3         struct llist_node    fu_llist; /* 文件对象链表 */
     4         struct rcu_head     fu_rcuhead; /* 释放之后的RCU链表 */
     5     } f_u;
     6     /* 目录项 */
     7     struct path        f_path;
     8     /* inode */
     9     struct inode        *f_inode;    /* cached value */
    10     /* 文件操作 */
    11     const struct file_operations    *f_op;
    12 
    13     /*
    14      * Protects f_ep_links, f_flags.
    15      * Must not be taken from IRQ context.
    16      */
    17     /**/
    18     spinlock_t        f_lock;
    19     /* 引用计数 */
    20     atomic_long_t        f_count;
    21     /* 打开文件时所指定的标志 */
    22     unsigned int         f_flags;
    23     /* 文件访问模式 */
    24     fmode_t            f_mode;
    25     struct mutex        f_pos_lock;
    26     /* 文件当前偏移量 */
    27     loff_t            f_pos;
    28     /* 拥有者通过信号进行异步IO数据传送 */
    29     struct fown_struct    f_owner;
    30     /* 文件的信任状 */
    31     const struct cred    *f_cred;
    32     /* 预读状态 */
    33     struct file_ra_state    f_ra;
    34     /* 版本号 */
    35     u64            f_version;
    36 #ifdef CONFIG_SECURITY
    37     /* 安全模块 */
    38     void            *f_security;
    39 #endif
    40     /* needed for tty driver, and maybe others */
    41     /* tty设备驱动的钩子 */
    42     void            *private_data;
    43 
    44 #ifdef CONFIG_EPOLL
    45     /* Used by fs/eventpoll.c to link all the hooks to this file */
    46     /* 事件池链表 */
    47     struct list_head    f_ep_links;
    48     struct list_head    f_tfile_llink;
    49 #endif /* #ifdef CONFIG_EPOLL */
    50     /* 页缓存映射 */
    51     struct address_space    *f_mapping;
    52 } __attribute__((aligned(4)));    /* lest something weird decides that 2 is OK */
    文件操作

    file_operations提供了文件操作函数,这些函数与系统调用进行关联;

     1 /* 文件操作 */
     2 struct file_operations {
     3     /* 拥有该模块的指针,通常被初始化为THIS_MODULE */
     4     struct module *owner;
     5     /* 
     6         用来修改文件的当前读写位置,并将新位置作为返回值,由系统调用lseek调用
     7         参数2是一个"长偏移量";
     8         参数3是SEEK_SET,SEEK_CUR,SEEK_END中的一个:
     9         SEEK_SET-参数2设置为新的读写位置
    10         SEEK_CUR-当前读写位置后增加参数2个偏移量
    11         SEEK_END-读写位置指向文件尾后再增加参数2个偏移量
    12     */
    13     loff_t (*llseek) (struct file *, loff_t, int);
    14     /* 
    15         从给定文件的offset偏移出读取count字节数据到buf中,
    16         同时更新文件指针,由系统调用read调用 
    17     */
    18     ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    19     /* 
    20         从给定buf中读取count字节数据,写入给定文件offset偏移处,
    21         同时更新文件指针,由系统调用write调用 
    22     */
    23     ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    24     /* 同步异步读写 */
    25     ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
    26     ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
    27 
    28     int (*iterate) (struct file *, struct dir_context *);
    29     int (*iterate_shared) (struct file *, struct dir_context *);
    30     /* 睡眠等待给定文件活动,由系统调用poll调用 */
    31     unsigned int (*poll) (struct file *, struct poll_table_struct *);
    32     /* 
    33         用来给设备发送名称参数对,当文件是一个被打开的设备节点时,
    34         可以通过它进行设置,由系统调用iotcl调用 
    35     */
    36     long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    37     /*
    38         是ioctl函数的可移植变种,被32位应用程序用在64位系统上,
    39         新的驱动程序应该设计自己的ioctl命令,以便所有的驱动程序都是可移植的,
    40         从而使得compat_ioctl和unlocked_ioctl指向同一个函数
    41     */
    42     long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    43     /* 将给定的文件映射到指定地址空间行,由系统调用mmap调用 */
    44     int (*mmap) (struct file *, struct vm_area_struct *);
    45     /* 创建一个新的文件对象,并将它和响应的索引节点对象关联起来,由系统调用open调用 */
    46     int (*open) (struct inode *, struct file *);
    47     /* 当已打开文件的引用计数减少时,该函数被VFS调用,它的作用根据具体文件系统而定 */
    48     int (*flush) (struct file *, fl_owner_t id);
    49     /*
    50         当文件最后一个引用被注销时(如当最后一个共享文件描述符进程调用了close()或者退出),
    51         该函数被VFS调用,它的作用根据具体文件系统而定 
    52 
    53     */
    54     int (*release) (struct inode *, struct file *);
    55     /* 将给定文件的所有被缓存数据写回磁盘,由系统调用fsync调用 */
    56     int (*fsync) (struct file *, loff_t, loff_t, int datasync);
    57     /* 打开或者关闭异步IO的通告信号 */
    58     int (*fasync) (int, struct file *, int);
    59     /* 给指定文件上锁 */
    60     int (*lock) (struct file *, int, struct file_lock *);
    61     /* 用来从一个文件向另外一个文件发送数据 */
    62     ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
    63     /* 在进程和地址空间中找到一个合适的位置,以便将底层设备中的内存段映射到该位置 */
    64     unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    65     /* 允许模块检查传递给fcntl(F_SETFL...)调用的标志 */
    66     int (*check_flags)(int);
    67     /* 实现flock()系统调用,该调用提供忠告锁 */
    68     int (*flock) (struct file *, int, struct file_lock *);
    69     ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
    70     ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
    71     int (*setlease)(struct file *, long, struct file_lock **, void **);
    72     long (*fallocate)(struct file *file, int mode, loff_t offset,
    73               loff_t len);
    74     void (*show_fdinfo)(struct seq_file *m, struct file *f);
    75 #ifndef CONFIG_MMU
    76     unsigned (*mmap_capabilities)(struct file *);
    77 #endif
    78     ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
    79             loff_t, size_t, unsigned int);
    80     int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,
    81             u64);
    82     ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
    83             u64);
    84 };
    inode对象

    内核用inode结构在内部表示文件,因此它和file结构不同,后者表示打开的文件描述符。对单个文件,可能会有多个表示打开文件描述符的file结构,但它们都指向单个inode结构;

    inode结构中包含了大量有关文件的信息。作为常规,只有下面两个字段对编写驱动程序代码有用

    dev_t i_rdev:

    对表示设备文件的inode结构,该字段包含了真正的设备编号;

    struct cdev *i_cdev:

    表示字符设备的内核的内部结构,当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针;

    从inode中获取主设备号和次设备号,使用下面函数,不要直接操作i_rdev:

    1 static inline unsigned iminor(const struct inode *inode)
    2 {
    3     return MINOR(inode->i_rdev);
    4 }
    5 
    6 static inline unsigned imajor(const struct inode *inode)
    7 {
    8     return MAJOR(inode->i_rdev);
    9 }
  • 相关阅读:
    log4j.properties配置详解
    maven常用命令集
    maven核心,pom.xml详解
    如何学习一门新技术?
    主题模型(概率潜语义分析PLSA、隐含狄利克雷分布LDA)
    聚类
    梯度下降中的学习率如何确定
    GPU版的tensorflow在windows上的安装时的错误解决方案
    maven笔记(maven使用与安装,eclipse中maven的配置,maven项目的创建)
    RNN的介绍
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11759653.html
Copyright © 2020-2023  润新知