1.在内核中file_operations源码 linux-2.6.38/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 { 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); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); 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); int (*aio_fsync) (struct kiocb *, 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 **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); };
1.struct module *owner
第一个file_operations 成员根本不是一个操作;它是一个指向拥有这个结构的模块的指针.这
个成员用来在它的操作还在被使用时阻止模块被卸载.几乎所有时间中,它被简单初始化为
THIS_MODULE, 一个在<linux/module.h> 中定义的宏.
2.loff_t (*llseek) (struct file *, loff_t, int);
llseek 方法用作改变文件中的当前读/写位置,并且新位置作为(正的)返回值.loff_t 参数是一
个"longoffset", 并且就算在32位平台上也至少64 位宽.错误由一个负返回值指示.如果这个
函数指针是NULL, seek 调用会以潜在地无法预知的方式修改file 结构中的位置计数器.
3.ssize_t (*read) (struct file *, char __user *, size_t, loff_t*);
用来从设备中获取数据.在这个位置的一个空指针导致read 系统调用以-EINVAL("Invalid
argument") 失败.一个非负返回值代表了成功读取的字节数(返回值是一个"signed size" 类型,
常常是目标平台本地的整数类型).
4.ssize_t (*aio_read)(struct kiocb *, char __user *, size_t,loff_t);
初始化一个异步读-- 可能在函数返回前不结束的读操作.如果这个方法是NULL, 所有的操
作会由read 代替进行(同步地).
5.ssize_t (*write) (struct file *, const char __user *, size_t,loff_t *);
发送数据给设备.如果NULL, -EINVAL 返回给调用write 系统调用的程序.如果非负,返回值
代表成功写的字节数.
6.ssize_t (*aio_write)(struct kiocb *, const char __user *,size_t, loff_t *);
初始化设备上的一个异步写.
7.int (*readdir) (struct file *, void *, filldir_t);
对于设备文件这个成员应当为NULL; 它用来读取目录,并且仅对文件系统有用.
8.unsigned int (*poll) (struct file *, struct poll_table_struct*);
poll 方法是3 个系统调用的后端:poll, epoll, 和select, 都用作查询对一个或多个文件描述符的
读或写是否会阻塞.poll 方法应当返回一个位掩码指示是否非阻塞的读或写是可能的,并且,
可能地,提供给内核信息用来使调用进程睡眠直到I/O 变为可能.如果一个驱动的poll 方法
为NULL, 设备假定为不阻塞地可读可写.
9.int (*ioctl) (struct inode *, struct file *, unsigned int,unsigned long);
ioctl 系统调用提供了发出设备特定命令的方法(例如格式化软盘的一个磁道,这不是读也不
是写).另外,几个ioctl 命令被内核识别而不必引用fops 表.如果设备不提供ioctl 方法,对于
任何未事先定义的请求(-ENOTTY,"设备无这样的ioctl"), 系统调用返回一个错误.
10.int (*mmap) (struct file *, struct vm_area_struct *);
mmap 用来请求将设备内存映射到进程的地址空间.如果这个方法是NULL, mmap 系统调用
返回-ENODEV.
11.int (*open) (struct inode *, struct file *);
尽管这常常是对设备文件进行的第一个操作,不要求驱动声明一个对应的方法.如果这个项
是NULL, 设备打开一直成功,但是你的驱动不会得到通知.
12.int (*flush) (struct file *);
flush 操作在进程关闭它的设备文件描述符的拷贝时调用;它应当执行(并且等待)设备的任何
未完成的操作.这个必须不要和用户查询请求的fsync 操作混淆了.当前,flush 在很少驱动中
使用;SCSI 磁带驱动使用它,例如,为确保所有写的数据在设备关闭前写到磁带上.如果flush
为NULL, 内核简单地忽略用户应用程序的请求.
13.int (*release) (struct inode *, struct file *);
在文件结构被释放时引用这个操作.如同open, release 可以为NULL.
14.int (*fsync) (struct file *, struct dentry *, int);
这个方法是fsync 系统调用的后端,用户调用来刷新任何挂着的数据.如果这个指针是
NULL, 系统调用返回-EINVAL.
15.int (*aio_fsync)(struct kiocb *, int);
这是fsync 方法的异步版本.
16.int (*fasync) (int, struct file *, int);
这个操作用来通知设备它的FASYNC 标志的改变.异步通知是一个高级的主题,在第6 章中
描述.这个成员可以是NULL如果驱动不支持异步通知.
17.int (*lock) (struct file *, int, struct file_lock *);
lock 方法用来实现文件加锁;加锁对常规文件是必不可少的特性,但是设备驱动几乎从不实
现它.
18.ssize_t (*readv) (struct file *, const struct iovec *, unsignedlong, loff_t *);
19.ssize_t (*writev) (struct file *, const struct iovec *,unsigned long, loff_t *);
这些方法实现发散/汇聚读和写操作.应用程序偶尔需要做一个包含多个内存区的单个读或
写操作;这些系统调用允许它们这样做而不必对数据进行额外拷贝.如果这些函数指针为
NULL, read 和write 方法被调用(可能多于一次).
20.ssize_t (*sendfile)(struct file *, loff_t *, size_t,read_actor_t, void *);
这个方法实现sendfile 系统调用的读,使用最少的拷贝从一个文件描述符搬移数据到另一个.
例如,它被一个需要发送文件内容到一个网络连接的web 服务器使用.设备驱动常常使
sendfile 为NULL.
21.ssize_t (*sendpage) (struct file *, struct page *, int, size_t,loff_t *, int);
sendpage 是sendfile 的另一半;它由内核调用来发送数据,一次一页,到对应的文件.设备驱动
实际上不实现sendpage.
22.unsigned long (*get_unmapped_area)(struct file *, unsignedlong, unsigned long, unsigned long, unsigned long);
这个方法的目的是在进程的地址空间找一个合适的位置来映射在底层设备上的内存段中.
这个任务通常由内存管理代码进行;这个方法存在为了使驱动能强制特殊设备可能有的任
何的对齐请求.大部分驱动可以置这个方法为NULL.[
23.int (*check_flags)(int)
这个方法允许模块检查传递给fnctl(F_SETFL...) 调用的标志.
24.int (*dir_notify)(struct file *, unsigned long);
这个方法在应用程序使用fcntl 来请求目录改变通知时调用.只对文件系统有用;驱动不需要
实现dir_notify.