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 }
原文地址:https://www.cnblogs.com/wanpengcoder/p/11759653.html