file_operations、file、inode结构释义

file_operations结构

file_operations结构体成员函数是字符设备驱动程序设计的主体内容,这些函数实际上会在应用程序执行open、close、read、write的时候被最终调用。定义在<linux/fs.h>中,重要成员如下。

struct file_operations {
	struct module *owner; // 拥有该结构的模块的指针,通常都是被定义为THIS_MODULE
	loff_t (*llseek) (struct file *, loff_t, int); // 用来修改文件当前读写的位置,并将新位置作为返回值返回
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); // 从设备中读取数据,当被负值为NULL的时候,read系统调用将出错,返回-EINVAL
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); // 向设备中发送数据
	ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
	ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
	int (*iopoll)(struct kiocb *kiocb, bool spin);
	int (*iterate) (struct file *, struct dir_context *);
	int (*iterate_shared) (struct file *, struct dir_context *);
	__poll_t (*poll) (struct file *, struct poll_table_struct *); // 是poll、epoll、select这三个系统调用的后端实现。用来查询某个或者多个文件描述符的读取或写入是否会阻塞。如果驱动程序将poll定义为NULL,则设备会被认为既可以读也可以写,并且不会阻塞
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); // 原ioctl,现被unlocked_ioctl取代,二者的区别在于unlocked_ioctl参数中少了inode,二者是兼容的
	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
	int (*mmap) (struct file *, struct vm_area_struct *);
	unsigned long mmap_supported_flags;
	int (*open) (struct inode *, struct file *); // 打开设备,如果设置为NULL,则设备的打开操作永远成功,但是系统不会通知驱动程序
	int (*flush) (struct file *, fl_owner_t id);
	int (*release) (struct inode *, struct file *); // 关闭设备,通open一样也可以设定为NULL
	int (*fsync) (struct file *, loff_t, loff_t, int datasync);
	int (*fasync) (int, struct file *, int);
	int (*lock) (struct file *, int, struct file_lock *);
	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file *, int, struct file_lock *);
	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
	int (*setlease)(struct file *, long, struct file_lock **, void **);
	long (*fallocate)(struct file *file, int mode, loff_t offset,
			  loff_t len);
	void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
	unsigned (*mmap_capabilities)(struct file *);
#endif
	ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
			loff_t, size_t, unsigned int);
	loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
				   struct file *file_out, loff_t pos_out,
				   loff_t len, unsigned int remap_flags);
	int (*fadvise)(struct file *, loff_t, loff_t, int);
} __randomize_layout;

 

file结构

定义在<linux/fs.h>中,file结构是一个内核结构,它不会出现在用户空间中。它由内核在open时创建,并传递给在该文件上进行操作的所有函数,直到最后的close函数。在文件的所有实例都被关闭之后,内核会释放这个数据结构。

struct file {
	union {
		struct llist_node	fu_llist;
		struct rcu_head 	fu_rcuhead;
	} f_u;
	struct path		f_path;
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op; // 与文件相关的操作,内核在执行open的时候为这个指针赋值,以后需要处理这些操作的时候就读取这个指针。

	/*
	 * Protects f_ep, f_flags.
	 * Must not be taken from IRQ context.
	 */
	spinlock_t		f_lock;
	enum rw_hint		f_write_hint;
	atomic_long_t		f_count;
	unsigned int 		f_flags; // 文件标志,例如O_RDONLY、O_NONBLOCK和O_SYNC。为了检查用户请求是否是阻塞式操作,需要检查O_NONBLOCK标志,其他标志很少用到。注意检查读写权限应该用f_mode而不是f_flags。
	fmode_t			f_mode; // 文件模式,通过FMODE_READ和FMODE_WRITE来标识文件是否可读或者可写。内核在调用驱动程序的read和write前已经检查了访问权限,驱动程序无需为此作额外的判断
	struct mutex		f_pos_lock;
	loff_t			f_pos; // 当前读写的位置。loff_t是一个64位的数(long long)如果驱动程序需要直到文件中当前的位置,可以读取这个值,但是不要去修改它。
	struct fown_struct	f_owner;
	const struct cred	*f_cred;
	struct file_ra_state	f_ra;

	u64			f_version;
#ifdef CONFIG_SECURITY
	void			*f_security;
#endif
	/* needed for tty driver, and maybe others */
	void			*private_data; // 在open的时候,这个指针会被置为NULL,驱动程序可以将这个字段用于任何目的或者忽略这个字段。

#ifdef CONFIG_EPOLL
	/* Used by fs/eventpoll.c to link all the hooks to this file */
	struct hlist_head	*f_ep;
#endif /* #ifdef CONFIG_EPOLL */
	struct address_space	*f_mapping;
	errseq_t		f_wb_err;
	errseq_t		f_sb_err; /* for syncfs */
} __randomize_layout

 

inode结构

内核用inode结构在内部表示文件,与file结构不同,file结构表示的是打开的文件描述符。
dev_t i_rdev; 对表示设备文件的inode结构,该字段包含了真正的设备编号。

可以通过下面的函数来获取主次设备号
次设备号:unsigned int iminor(struct inode *inode);
主设备号:unsigned int imajor(struct inode *inode);

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
file_operations是Linux内核中的一个结构体,用于定义文件操作相关的函数指针,包括文件的打开、关闭、读取、写入等操作。 该结构体的定义如下: ```c 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 (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*fsync) (struct file *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **, void **); long (*fallocate)(struct file *, int, loff_t, loff_t); }; ``` 其中,各个函数指针的含义如下: - `owner`:指向模块的指针,用于内存管理。 - `llseek`:将文件指针定位到给定的偏移量。 - `read`:从文件中读取数据。 - `write`:向文件中写入数据。 - `open`:打开文件。 - `release`:关闭文件。 - `flush`:刷新文件缓存。 - `fsync`:将文件同步到磁盘。 - `fasync`:设置异步通知。 - `lock`:对文件进行加锁。 - `sendpage`:将文件中的一页发送给网络。 - `get_unmapped_area`:为文件映射内存。 - `check_flags`:检查文件打开标志。 - `flock`:锁定文件。 - `splice_write`:将数据从文件传输到管道。 - `splice_read`:将数据从管道传输到文件。 - `setlease`:设置文件租约。 - `fallocate`:为文件预分配磁盘空间。 file_operations结构体定义了Linux内核中文件系统的接口,让不同的文件系统能够共用相同的接口,从而实现更好的兼容性和可移植性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值