在上一节中介绍了字符设备的重要结构体 cdev,以及和 cdev 相关的一些操作函数,比如cdev_alloc()、 cdev_init() 等,但是和 cdev_init() 密切相关的一个参数 fops,并没有介绍。这节重点分析 file_operations 结构体。
file_operations 结构体的成员函数是字符设备驱动程序设计的主体内容,这些内容实际上,是会通过Linux的系统调用,比如 open() 、write()等调用到的。
// (include\linux\Fs.h)
/*
* NOTE:
* all file operations except setlease can be called without
* the big kernel lock held in all filesystems.
*/
struct file_operations {
//拥有该结构的模块的指针,一般设置为THIS_MODULE
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 *);
//异步的读取操作
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
//异步的写操作
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
//仅用于读取目录,对设备文件一般为NULL
int (*readdir) (struct file *, void *, filldir_t);
//轮询函数,判断当前是否可以进行非堵塞的读取和写入
unsigned int (*poll) (struct file *, struct poll_table_struct *);
//执行设备I/O控制命令
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
//用于请求将设备内存映射到进程地址空间
int (*mmap) (struct file *, struct vm_area_struct *);
//打开
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
//关闭
int (*release) (struct inode *, struct file *);
//刷新待处理缓冲区
int (*fsync) (struct file *, int datasync);
//异步sync
int (*aio_fsync) (struct kiocb *, int datasync);
//通知设备FASYNC标识发生变化
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 **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
总结一下在字符设备中,涉及较多的file_operations的成员函数
在用户空间执行系统调用的时候,比如 open(),会调用到对应设备的file_operations的成员函数。 这样用户空间的操作,对可以由对应的字符设备的file_opeations的成员函数来实现。
Linux 设备驱动开发详解 (宋宝华) 第二版