1.在內核中file_operations源碼 linux-2.6.38/include/linux/fs.h
[cpp]
/*
* 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);
};
/*
* 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.