http://blog./jinxilee/Category.htm?ID=1199 詳解Linux2.6內(nèi)核中基于platform機(jī)制的驅(qū)動模型linux驅(qū)動程序中最重要的涉及3個重要的內(nèi)核數(shù)據(jù)結(jié)構(gòu),分別為file_operations,file和inode。 在linux中inode結(jié)構(gòu)用于表示文件,而file結(jié)構(gòu)則表示打開的文件的描述,因為對于單個文件而言可能會有許多個表示打開的文件的描述符,因而就可能會的對應(yīng)有多個file結(jié)構(gòu),,但是都指向單個inode結(jié)構(gòu)。 在系統(tǒng)內(nèi)部,,I/O設(shè)備的存取操作通過特定的的入口來進(jìn)行,,而這組特定的入口由驅(qū)動程序來提供的。通常這組設(shè)備驅(qū)動的接口是由結(jié)構(gòu)體file_operations向系統(tǒng)說明的,,它定義在include/linux/fs.h中,。 file_operations的數(shù)據(jù)結(jié)構(gòu)如下:(2.6內(nèi)核) struct file_operations{ struct module *owner;//擁有該模塊的指針,一般THIS_MODULE loff_t (*llseek) (struct file*, loff_t,int);//修改文件當(dāng)前的讀寫位置 ssize_t (*read)(struct file *,,char *, size_t, loff_t *); //從設(shè)備同步讀取數(shù)據(jù) ssize_t (*write)(struct file *,const char *, size_t, loff_t *); //向設(shè)備發(fā)送數(shù)據(jù) int (*readdir) (struct file *, void *, filldir_t); //僅用于讀取目錄,,對于設(shè)備文件,該字段為NULL unsigned int (*poll)(struct file *, struct poll_table_struct *); //輪詢函數(shù),,判斷目前是否可以進(jìn)行非阻塞的讀取或?qū)懭?/font> int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //執(zhí)行設(shè)備IO控制命令 int (*mmap) (sturct file *, struct vm_area_struct*); //用于請求將設(shè)備內(nèi)存映射到進(jìn)程地址空間 int (*open) (struct inode *, struct file *);//打開 int (*flush)(struct file *); int (*release)(struct inode *, struct file *);//關(guān)閉 int (*synch)(struct file *, struct dentry *, int datasync);//刷新待處理的數(shù)據(jù) int (*fasync)(int, struct file *, int);//通知設(shè)備fasync標(biāo)志發(fā)生變化 int (*lock)(struct file *, int, struct file_lock); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long*, loff_t * ); sszie_t(*writev)(struct file *, const struct iovec *, unsigned long *, loff_t *);//分散聚集型的讀寫 ssize_t (*sengpage)(struct file *, struct page *, int, size_t,loff_t *, int); unsigned long (*get_unmaapped_area)(struct file *,unsigned long, unsigned long, unsigned long, unsigned long ); long (*fcntl)(int fd, unsigned int cmd,unsigned arg, struct file *filp); }; 隨著內(nèi)核的不斷升級,,file_operations結(jié)構(gòu)也會越來越大,不同版本會稍有不同,。 一般的設(shè)備驅(qū)動程序只需用到上面的藍(lán)色部分的五個函數(shù),! Linux的設(shè)備文件是同硬件一一對應(yīng)的,因而對設(shè)備的操作可以通過對設(shè)備文件的操作來實現(xiàn),。而這些操作的實現(xiàn)其實就是對一些標(biāo)準(zhǔn)的系統(tǒng)調(diào)用,,如open(), read(),,write(),,close()等。實際上file_operations就是把系統(tǒng)調(diào)用和驅(qū)動程序 關(guān)聯(lián)起來的關(guān)鍵數(shù)據(jù)結(jié)構(gòu),。這個結(jié)構(gòu)的每一成員都對應(yīng)著一個系統(tǒng)調(diào)用。當(dāng)用戶進(jìn)程利用系統(tǒng)調(diào)用對設(shè)備進(jìn)行讀寫操作的時候,,這些系統(tǒng)調(diào)用通過設(shè)備的主設(shè)備號和 次設(shè)備號來確定相應(yīng)的驅(qū)動程序,,然后讀取file_operations中相應(yīng)的函數(shù)指針,接著把控制權(quán)交給函數(shù),從而完成linux設(shè)備驅(qū)動程序的工 作,。
struct file提供關(guān)于被打開的文件信息,,主要供與文件系統(tǒng)對應(yīng)的設(shè)備文件驅(qū)動程序使用。結(jié)構(gòu)如下: struct file{ mode_t f_mode;//表示文件是否可讀或可寫,,F(xiàn)MODE_READ或FMODE_WRITE dev_ t f_rdev ;// 用于/dev/tty off_t f_ops;//當(dāng)前文件位移 unsigned short f_flags,;//文件標(biāo)志,O_RDONLY,O_NONBLOCK和O_SYNC unsigned short f_count,;//打開的文件數(shù)目 unsigned short f_reada,; struct inode *f_inode;//指向inode的結(jié)構(gòu)指針 struct file_operations *f_op,;//文件索引指針 }
還有 struct device_struct 在系統(tǒng)啟動過程中的塊設(shè)備和字符設(shè)備管理表的定義在文件fs/device.h中 struct device_struct { const char *name,; struct file_operations *fops; } static struct device_struct chrdevs[MAX_CHRDEV]; static struct device_struct blkdevs[MAX_BLKDEV];
其實塊設(shè)備表和字符設(shè)備表使用了相同的數(shù)據(jù)結(jié)構(gòu),。這些設(shè)備表也稱作設(shè)備開關(guān)表,,不同的是他們定義了一組函數(shù)指針對設(shè) 備進(jìn)行管理。而這里系統(tǒng)用文件操作(file_operations)代替了那組開關(guān),。文件操作是文件系統(tǒng)與驅(qū)動程序之間的接口,,系統(tǒng)特殊文件在建立的時 候并沒有把兩者對應(yīng)起來,只是把設(shè)備的默認(rèn)文件結(jié)構(gòu)和i節(jié)點結(jié)構(gòu)賦給設(shè)備文件,,而真正的對應(yīng)定義在系統(tǒng)啟動后,,當(dāng)設(shè)備被打開時才進(jìn)行的。 |
|