前面说到,Linux的设备驱动程序的大致流程。目前驱动模块的加载与卸载、驱动程序的注册与注销这几个部分,已经在前面介绍了。剩下就是设备的打开与释放、设备的读写操作、设备的控制操作、设备的中断和轮询处理等这几个部分了。在此部分介绍之前不得不介绍设备驱动开发的重要函数。
对于字符设备的操作函数集合
include/linux/fs.h文件中struct file_operations {
…}
对于块设备的操作函数集合:
include/linux/blkdev.h文件中struct block_device_operations {
…}
对于网络设备的操作函数:
include/linux/netdevice.h文件中struct net_device_ops{
…}
本文以字符设备驱动开发为例。在Linux内核4.x下,编写驱动程序实际上是实现对设备文件对应操作函数的编写,而这些操作函数是结构体file_operations中函数指针所指函数的具体实现。file_operations在Linux系统下的include/linux/fs.h 中可以找到定义,该结构体的每个域都对应着驱动内核模块用来处理某个被请求的事件的函数的地址。(ps:这其实也就是函数指针的功能)
1 struct file_operations {
2 struct module *owner; /*拥有该结构的模块的指针,一般为THIS_MODULES*/
3 loff_t (*llseek) (struct file *, loff_t, int); /* 用来修改文件当前的读写位置 */
4 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); /*从设备中同步读取数据*/
5 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); /*向设备发送数据*/
6 ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
7 ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
8 int (*iterate) (struct file *, struct dir_context *);
9 unsigned int (*poll) (struct file *, struct poll_table_struct *); /*轮询函数,判断目前是否可以进行非阻塞的读写或写入*/
10 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); /*执行设备I/O控制命令*/
11 long (*compat_ioctl) (struct file *, unsigned int, unsigned long); /*在64位系统上,32位的ioctl调用将使用此函数指针代替*/
12 int (*mmap) (struct file *, struct vm_area_struct *); /*用来请求将设备内存映射到进程的地址空间*/
13 int (*mremap)(struct file *, struct vm_area_struct *);
14 int (*open) (struct inode *, struct file *);
15 int (*flush) (struct file *, fl_owner_t id); /*进程关闭它的设备文件描述符的拷贝时调用*/
16 int (*release) (struct inode *, struct file *); /*清理未结束的输入输出操作,释放资源,用户自定义排他标志的复位等*/
17 int (*fsync) (struct file *, loff_t, loff_t, int datasync); /*刷新待处理的数据,允许进程把所有的脏缓冲区刷新到磁盘*/
18 int (*aio_fsync) (struct kiocb *, int datasync); /*调用fsync把文件所指定的文件的所有缓冲区写到磁盘中*/
19 int (*fasync) (int, struct file *, int); /*系统支持异步通知的设备驱动*/
20 int (*lock) (struct file *, int, struct file_lock *); /*用来实现文件加锁*/
21 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); /*由内核调用来发送数据, 一次一页, 到对应的文件*/
22 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
23 int (*check_flags)(int); /*允许模块检查传递给 fnctl(F_SETFL...) 调用的标志*/
24 int (*flock) (struct file *, int, struct file_lock *);
25 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);