linux 基礎復習(9)設備驅動入門
Linux 內核中采用可加載的模塊化設計(LKMs,Loadable Kernel Modules),一般情況下編譯的Linux 內核是支持可插入式模塊的,也就是將最基本的核心代碼編譯在內核中,其他的代碼可以選擇在內核中,或者編譯為內核的模塊文件。常見的驅動程序也是作為內核模塊動態加載的。
本文引用地址:http://www.j9360.com/article/201610/305814.htm模塊相關命令
lsmod 列出當前系統加載的模塊
rmmod 將當前模塊卸載
insmod、modprobe 用于加載當前模塊。但insmod不會自動解決依存關系,而modprobe可以根據模塊間的依存關系以及 /etc/modules.conf 文件中的內容自動插入模塊
mknod 創建相關模塊
Linux 系統的設備文件分為三類:塊設備文件、字符設備文件和網絡設備文件。
· 塊設備文件通常指一些需要以塊(如512 字節)的方式寫入的設備,如IDE 硬盤、SCSI硬盤、光驅等。
· 字符型設備文件通常指可以直接讀寫,沒有緩沖區的設備,如并口、虛擬控制臺等。
· 網絡設備文件通常是指網絡設備訪問的BSD socket接口,如網卡等。
設備號設備號是一個數字,它是設備的標志。就如前面所述,一個設備文件(也就是設備節點)可以通過mknod命令來創建,其中指定了主設備號和次設備號。主設備號表明某一類設備,
一般對應著確定的驅動程序;次設備號一般是用于區分標明不同屬性,例如不同的使用方法,不同的位置,不同的操作等,它標志著某個具體的物理設備。高字節為主設備號和底字節為次設備號。例如,在系統中的塊設備IDE 硬盤的主設備號是3,而多個IDE 硬盤及其各個分區分別賦予次設備號1、2、3……
Linux 設備驅動程序包含中斷處理程序和設備服務子程序兩部分
設備服務子程序包含了所有與設備操作相關的處理代碼。它從面向用戶進程的設備文件系統中接受用戶命令,并對設備控制器執行操作。這樣,設備驅動程序屏蔽了設備的特殊性,使用戶可以像對待文件一樣操作設備。
設備控制器需要獲得系統服務時有兩種方式:查詢和中斷。因為Linux 下的設備驅動程序是內核的一部分,在設備查詢期間系統不能運行其他代碼,查詢方式的工作效率比較低,所以只有少數設備如軟盤驅動程序采取這種方式,大多設備以中斷方式向設備驅動程序發出輸入/輸出請求。
screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new windownCTRL+Mouse wheel to zoom in/out';} onclick=if(!this.resized) {return true;} else {window.open(this.src);} alt= src=http://blogimg.chinaunix.net/blog/upfile2/080413193842.jpg onload=if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new windownCTRL+Mouse wheel to zoom in/out';} border=0>
Linux 中的設備驅動程序有如下特點。
(1)內核代碼:設備驅動程序是內核的一部分,如果驅動程序出錯,則可能導致系統崩潰。
(2)內核接口:設備驅動程序必須為內核或者其子系統提供一個標準接口。比如,一個終端驅動程序必須為內核提供一個文件I/O 接口;一個SCSI設備驅動程序應該為SCSI子系統提供一個SCSI設備接口,同時SCSI子系統也必須為內核提供文件的I/O 接口及緩沖區。
(3)內核機制和服務:設備驅動程序使用一些標準的內核服務,如內存分配等。
(4)可裝載:大多數的Linux 操作系統設備驅動程序都可以在需要時裝載進內核,在不需要時從內核中卸載。
(5)可設置:Linux 操作系統設備驅動程序可以集成為內核的一部分,并可以根據需要把其中的某一部分集成到內核中,這只需要在系統編譯時進行相應的設置即可。
(6)動態性:在系統啟動且各個設備驅動程序初始化后,驅動程序將維護其控制的設備。
如果該設備驅動程序控制的設備不存在也不影響系統的運行,那么此時的設備驅動程序只是多占用了一點系統內存罷了。
驅動開發時卻沒有main 函數,模塊在調用insmod命令時被加載,此時的入口點是init_module函數,通常在該函數中完成設備的注冊。同樣,模塊在調rmmod
函數時被卸載,此時的入口點是cleanup_module函數,在該函數中完成設備的卸載。在設備完成注冊加載之后,用戶的應用程序就可以對該設備進行一定的操作,如read、write等,而驅動程序就是用于實現這些操作,在用戶應用程序調用相應入口函數時執行相關的操作,init_module入口點函數則不需要完成其他如read、write之類功能。
設備驅動程序的入口點,它是一個在中定義的struct file結構,這是一個內核結構,不會出現在用戶空間的程序中,它定義了常見文件I/O 函數的入口。
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *filp, char *buff, size_t count, loff_t *offp);
ssize_t (*write) (struct file *filp, const char *buff, size_t count, loff_t *offp);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned
long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *);
int (*fasync) (int, struct file *, int);
int (*check_media_change) (kdev_t dev);
int (*revalidate) (kdev_t dev);
int (*lock) (struct file *, int, struct file_lock *);
};
每個設備的驅動程序不一定要實現其中所有的函數操作,若不需要定義實現時,則只需將其設為NULL即可。
評論