[2017年整理]file_operations结构体详细分析

上传人:豆浆 文档编号:910132 上传时间:2017-05-21 格式:DOCX 页数:4 大小:19.38KB
返回 下载 相关 举报
[2017年整理]file_operations结构体详细分析_第1页
第1页 / 共4页
[2017年整理]file_operations结构体详细分析_第2页
第2页 / 共4页
[2017年整理]file_operations结构体详细分析_第3页
第3页 / 共4页
[2017年整理]file_operations结构体详细分析_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《[2017年整理]file_operations结构体详细分析》由会员分享,可在线阅读,更多相关《[2017年整理]file_operations结构体详细分析(4页珍藏版)》请在金锄头文库上搜索。

1、file_operations 结构体详细分析第一个 file_operations 成员根本不是一个操作; 它是一个指向拥有这个结构的模块的指针 .这个成员用来在它的操作还在被使用时阻止模块被卸载. 几乎所有时间中, 它被简单初始化为 THIS_MODULE, 一个在 中定义的宏.这个宏比较复杂,在进行简单学习操作的时候,一般初始化为 THIS_MODULE。loff_t (*llseek) (struct file * filp , loff_t p, int orig);(指针参数 filp 为进行读取信息的目标文件结构体指针;参数 p 为文件定位的目标偏移量;参数 orig 为对文件定

2、位的起始地址,这个值可以为文件开头(SEEK_SET,0, 当前位置(SEEK_CUR,1),文件末尾(SEEK_END,2))llseek 方法用作改变文件中的当前读/写位置, 并且新位置作为(正的) 返回值.loff_t 参数是一个long offset, 并且就算在 32 位平台上也至少 64 位宽. 错误由一个负返回值指示.如果这个函数指针是 NULL, seek 调用会以潜在地无法预知的方式修改 file 结构中的位置计数器( 在file 结构 一节中描述).ssize_t (*read) (struct file * filp, char _user * buffer, size_

3、t size , loff_t * p);(指针参数 filp 为进行读取信息的目标文件,指针参数 buffer 为对应放置信息的缓冲区(即用户空间内存地址) ,参数 size 为要读取的信息长度,参数 p 为读的位置相对于文件开头的偏移,在读取信息后,这个指针一般都会移动,移动的值为要读取信息的长度值)这个函数用来从设备中获取数据. 在这个位置的一个空指针导致 read 系统调用以 -EINVAL(Invalid argument) 失败.一个非负返回值代表了成功读取的字节数( 返回值是一个 signed size 类型, 常常是目标平台本地的整数类型).ssize_t (*aio_read

4、)(struct kiocb * , char _user * buffer, size_t size , loff_t p);可以看出,这个函数的第一、三个参数和本结构体中的 read()函数的第一、三个参数是不同 的,异步读写的第三个参数直接传递值,而同步读写的第三个参数传递的是指针,因为 AIO 从来不需要改变文件的位置。异步读写的第一个参数为指向 kiocb 结构体的指针,而同步读写的第一参数为指向 file 结构体的指针,每一个 I/O 请求都对应一个 kiocb 结构体);初始化一个异步读 - 可能在函数返回前不结束的读操作.如果这个方法是 NULL, 所有的操作会由 read 代

5、替进行(同步地).(有关 linux 异步 I/O,可以参考有关的资料, linux 设备驱动开发详解中给出了详细的解答)ssize_t (*write) (struct file * filp, const char _user * buffer, size_t count, loff_t * ppos);(参数 filp 为目标文件结构体指针,buffer 为要写入文件的信息缓冲区, count 为要写入信息的长度,ppos 为当前的偏移位置,这个值通常是用来判断写文件是否越界)发送数据给设备. 如果 NULL, -EINVAL 返回给调用 write 系统调用的程序. 如果非负, 返回值

6、代表成功写的字节数.(注:这个操作和上面的对文件进行读的操作均为阻塞操作)ssize_t (*aio_write)(struct kiocb *, const char _user * buffer, size_t count, loff_t * ppos);初始化设备上的一个异步写.参数类型同 aio_read()函数;int (*readdir) (struct file * filp, void *, filldir_t);对于设备文件这个成员应当为 NULL; 它用来读取目录, 并且仅对文件系统有用.unsigned int (*poll) (struct file *, struct

7、 poll_table_struct *);(这是一个设备驱动中的轮询函数,第一个参数为 file 结构指针,第二个为轮询表指针)这个函数返回设备资源的可获取状态,即POLLIN,POLLOUT,POLLPRI,POLLERR,POLLNVAL 等宏的位“或” 结果。每个宏都表明设备的一种状态,如:POLLIN(定义为 0x0001)意味着设备可以无阻塞的读,POLLOUT(定义为 0x0004)意味着设备可以无阻塞的写。(poll 方法是 3 个系统调用的后端: poll, epoll, 和 select, 都用作查询对一个或多个文件描述符的读或写是否会阻塞.poll 方法应当返回一个位掩码

8、指示是否非阻塞的读或写是可能的 , 并且, 可能地, 提供给内核信息用来使调用进程睡眠直到 I/O 变为可能. 如果一个驱动的 poll 方法为 NULL, 设备假定为不阻塞地可读可写.(这里通常将设备看作一个文件进行相关的操作,而轮询操作的取值直接关系到设备的响应情况,可以是阻塞操作结果,同时也可以是非阻塞操作结果)int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);(inode 和 filp 指针是对应应用程序传递的文件描述符 fd 的值, 和传递给 open

9、方法的相同参数.cmd 参数从用户那里不改变地传下来, 并且可选的参数 arg 参数以一个 unsigned long 的形式传递, 不管它是否由用户给定为一个整数或一个指针.如果调用程序不传递第 3 个参数, 被驱动操作收到的 arg 值是无定义的.因为类型检查在这个额外参数上被关闭, 编译器不能警告你如果一个无效的参数被传递给 ioctl, 并且任何关联的错误将难以查找.)ioctl 系统调用提供了发出设备特定命令的方法(例如格式化软盘的一个磁道, 这不是读也不是写).另外, 几个 ioctl 命令被内核识别而不必引用 fops 表.如果设备不提供 ioctl 方法, 对于任何未事先定义的

10、请求(-ENOTTY, 设备无这样的 ioctl), 系统调用返回一个错误.int (*mmap) (struct file *, struct vm_area_struct *);mmap 用来请求将设备内存映射到进程的地址空间. 如果这个方法是 NULL, mmap 系统调用返回 -ENODEV.(如果想对这个函数有个彻底的了解,那么请看有关“进程地址空间”介绍的书籍)int (*open) (struct inode * inode , struct file * filp ) ;(inode 为文件节点,这个节点只有一个,无论用户打开多少个文件,都只是对应着一个 inode 结构;但是

11、 filp 就不同,只要打开一个文件,就对应着一个 file 结构体, file 结构体通常用来追踪文件在运行时的状态信息)尽管这常常是对设备文件进行的第一个操作, 不要求驱动声明一个对应的方法. 如果这个项是 NULL, 设备打开一直成功, 但是你的驱动不会得到通知.与 open()函数对应的是 release()函数。int (*flush) (struct file *);flush 操作在进程关闭它的设备文件描述符的拷贝时调用; 它应当执行(并且等待) 设备的任何未完成的操作.这个必须不要和用户查询请求的 fsync 操作混淆了. 当前, flush 在很少驱动中使用;SCSI 磁带驱

12、动使用它 , 例如, 为确保所有写的数据在设备关闭前写到磁带上 . 如果 flush 为 NULL, 内核简单地忽略用户应用程序的请求.int (*release) (struct inode *, struct file *);release ()函数当最后一个打开设备的用户进程执行 close()系统调用的时候,内核将调用驱动程序 release()函数:void release(struct inode inode,struct file *file),release 函数的主要任务是清理未结束的输入输出操作,释放资源,用户自定义排他标志的复位等。在文件结构被释放时引用这个操作. 如同

13、open, release 可以为 NULL.int(*synch)(struct file *,struct dentry *,int datasync);刷新待处理的数据,允许进程把所有的脏缓冲区刷新到磁盘。int (*aio_fsync)(struct kiocb *, int);这是 fsync 方法的异步版本.所谓的 fsync 方法是一个系统调用函数。系统调用 fsync把文件所指定的文件的所有脏缓冲区写到磁盘中(如果需要,还包括存有索引节点的缓冲区) 。相应的服务例程获得文件对象的地址,并随后调用 fsync 方法。通常这个方法以调用函数_writeback_single_ino

14、de()结束,这个函数把与被选中的索引节点相关的脏页和索引节点本身都写回磁盘。int (*fasync) (int, struct file *, int);这个函数是系统支持异步通知的设备驱动,下面是这个函数的模板:static int *_fasync(int fd,struct file *filp,int mode)struct *_dev * dev=filp-private_data;return fasync_helper(fd,filp,mode,&dev-async_queue);/第四个参数为 fasync_struct 结构体指针的指针。/这个函数是用来处理 FASYNC

15、 标志的函数。 (FASYNC:表示兼容 BSD 的 fcntl 同步操作)当这个标志改变时,驱动程序中的 fasync()函数将得到执行。此操作用来通知设备它的 FASYNC 标志的改变. 异步通知是一个高级的主题, 在第 6 章中描述.这个成员可以是 NULL 如果驱动不支持异步通知 .int (*lock) (struct file *, int, struct file_lock *);lock 方法用来实现文件加锁; 加锁对常规文件是必不可少的特性, 但是设备驱动几乎从不实现它.ssize_t (*readv) (struct file *, const struct iovec *

16、, unsigned long, loff_t *);ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);这些方法实现发散/汇聚读和写操作. 应用程序偶尔需要做一个包含多个内存区的单个读或写操作;这些系统调用允许它们这样做而不必对数据进行额外拷贝. 如果这些函数指针为 NULL, read 和 write 方法被调用( 可能多于一次 ).ssize_t (*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void *);这个方法实现 sendfile 系统调用的读, 使用最少的拷贝从一个文件描述符搬移数据到另一个.例如, 它被一个需要发送文件内容到一个网络连接的 web 服务器使用. 设备驱动常常使 sendfile 为 NULL.ssize_t (*sendpage) (struct

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号