结构体file_operations
的定义和各成员函数的作用
结构体file_operations
的完整定义可参考下面这篇博文:
http://iyenn.com/rec/1709536.html
因为定义比较长,所以这里只截取部分作为其简单定义,能把问题说明清楚就行。
简单定义如下:
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 *);
long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
...
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
从这个定义我们可以看出,file_operations
中最常用的 open
、read
、write
和 release
函数都有固定的参数形式和返回值类型,内核通过这些标准化的接口来调用驱动程序。这些函数的原型是固定的,驱动程序必须遵循这些原型,以便内核能够正确调用并与驱动程序进行交互。
它们的作用和何时被调用的情况分别如下:
open
:当文件被打开时调用,比如系统内核函数open会调用它。read
:当文件被读取时调用,比如系统内核函数read会调用它。write
:当数据写入文件时调用,比如系统内核函数write会调用它。release
:当文件被关闭时调用,比如系统内核函数close会调用它,典型的语句为close(fd)
。
各操作函数的参数意义
下面介绍这些函数的固定参数的意义。
下面这几个函数都或多或少的用到了参数inode和file,关于这两个参数的详细介绍,请参考下面这篇博文:
http://iyenn.com/rec/1709313.html
下面这几个函数都或多或少的用到了参数inode和file,关于这两个参数的详细介绍,请参考下面这篇博文:
http://iyenn.com/rec/1709313.html
下面这几个函数都或多或少的用到了参数inode和file,关于这两个参数的详细介绍,请参考下面这篇博文:
http://iyenn.com/rec/1709313.html
所以在下面对各参数的介绍中,就不再对参数inode和file作深入的介绍了。
1. open
操作函数
int (*open) (struct inode *inode, struct file *file);
- 1
inode
:指向文件的inode
结构体,表示文件的元数据。通过inode
,驱动程序可以获取文件的状态、权限等信息。调用文件操作结构体file_operations中open操作函数时,内核会把系统中的inode实例赋给它。file
:指向与打开的文件相关的struct file
结构体,包含与文件操作相关的状态信息,对于驱动程序,还可以通过它的成员private_data
访问和管理文件的私有数据。调用文件操作结构体file_operations中open操作函数时,内核会把系统中的file实例赋给它。
open
成员函数在系统内核的open函数每次打开文件时被调用。你可以在这个函数中初始化一些设备的状态或分配资源。
2. read
操作函数
ssize_t (*read) (struct file *file, char __user *buf, size_t count, loff_t *offset);
- 1
file
:指向与打开的文件相关的struct file
结构体。包含了文件的私有数据、状态等信息。buf
:指向用户空间的缓冲区,内核会将数据从内核空间复制到这个缓冲区。这个参数由系统内核的read函数传递给它,系统内核的read函数的原型为:ssize_t read(int fd, void *buf, size_t count);
,这里面的参数void *buf
会传递给read
操作函数的参数char __user *buf
。count
:表示请求读取的数据量。这个参数由系统内核的read函数传递给它,系统内核的read函数的原型为:ssize_t read(int fd, void *buf, size_t count);
,这里面的参数size_t count
会传递给read
操作函数的参数size_t count
。offset
:文件或设备的当前偏移量,内核会在每次读取操作时传递给驱动程序,并且在读取后自动更新它。这个量实际上存储在每个文件中struct file
实例中的,调用文件操作结构体file_operations中的read操作函数时,系统会把这个量自动赋给它。
值得注意的是,这个函数的返回值类型是ssize_t,它表示从内核空间读取了多少个字节的数据到用户空间。它的返回值也会作为系统内核函数read的返回值。
read
成员函数在每次读取操作时被调用,比如系统内核函数read会调用它,驱动程序需要将数据从内核缓冲区复制到用户缓冲区。
3. write
操作函数
ssize_t (*write) (struct file *file, const char __user *buf, size_t count, loff_t *offset);
- 1
file
:指向与打开的文件相关的struct file
结构体。buf
:指向用户空间的缓冲区,内核会将用户空间的数据从buf
复制到内核空间。这个参数由系统内核的write函数传递给它,系统内核的write函数的原型为:ssize_t write(int fd, const void *buf, size_t count);
,这里面的参数const void *buf
会传递给write
操作函数的参数const char __user *buf,
。这里面的const表示缓冲区数据不能被修改,这是为了防止在写入数据的过程中,源数据被意外修改。count
:表示请求写入的数据量。这个参数由系统内核的write函数传递给它,系统内核的write函数的原型为:ssize_t write(int fd, const void *buf, size_t count);
,这里面的参数size_t count
会传递给write
操作函数的参数size_t count
。offset
:文件或设备的当前偏移量,内核会在每次写入操作时传递给驱动程序,并且在写入后自动更新它。这个量实际上存储在每个文件中struct file
实例中的,调用文件操作结构体file_operations中的write操作函数时,系统会把这个量自动赋给它。
值得注意的是,这个函数的返回值类型是ssize_t,它表示写入了多个字节的数据到内核空间。它的返回值也会作为系统内核函数write的返回值。
write
函数在每次写入操作时被调用,比如系统内核函数write会调用它,驱动程序需要将数据从用户缓冲区复制到内核缓冲区或设备。
4. release
操作函数
int (*release) (struct inode *inode, struct file *file);
- 1
inode
:指向文件的inode
结构体,表示文件的元数据。file
:指向与文件相关的struct file
结构体,包含文件的私有数据和状态信息。
release
函数在文件关闭时被调用,比如系统内核函数close会调用它,典型的语句如close(fd)
。驱动程序可以在这里清理资源,例如释放在 open
函数中分配的内存或关闭设备。
总结
是的,file_operations
中的 open
、read
、write
和 release
函数都具有固定的参数形式。这些函数的签名由内核定义,驱动程序必须按照这些签名来实现相应的操作。通过这些函数,内核与设备驱动之间能够进行标准化的交互,保证设备操作的一致性和可管理性。



评论记录:
回复评论: