文件对象
文件对象是进程已经打开文件描述符的内存中的表示,单个文件可能有多个表示打开文件描述符的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 }