嵌入式Linux驅動(dòng)程序開(kāi)發(fā)要點(diǎn)
在Linux操作系統下有3類(lèi)主要的設備文件類(lèi)型:塊設備、字符設備和網(wǎng)絡(luò )設備。這種分類(lèi)方法可以將控制輸入/輸出設備的驅動(dòng)程序與其他操作系統軟件分離開(kāi)來(lái)。
本文引用地址:http://dyxdggzs.com/article/148529.htm字符設備與塊設備的主要區別是:在對字符設備發(fā)出讀/寫(xiě)請求時(shí),實(shí)際的硬件I/O一般緊接著(zhù)發(fā)生。塊設備則不然,它利用一塊系統內存作為緩沖區,若用戶(hù)進(jìn)程對設備的請求能滿(mǎn)足用戶(hù)的要求,就返回請求的數據;否則,就調用請求函數來(lái)進(jìn)行實(shí)際的I/O操作。塊設備主要是針對磁盤(pán)等慢速設備設計的,以免耗費過(guò)多的CPU時(shí)間用來(lái)等待。網(wǎng)絡(luò )設備可以通過(guò)BSD套接口訪(fǎng)問(wèn)數據。
每個(gè)設備文件都有其文件屬性(c/b),表示是字符設備還是塊設備。另外每個(gè)文件都有2個(gè)設備號,第一個(gè)是主設備號,標識驅動(dòng)程序;第二個(gè)是從設備號,標識使用同一個(gè)設備驅動(dòng)程序的、不同的硬件設備。設備文件的主設備號必須與設備驅動(dòng)程序在登記時(shí)申請的主設備號一致,否則用戶(hù)進(jìn)程將無(wú)法訪(fǎng)問(wèn)驅動(dòng)程序。
系統調用時(shí)操作系統內核與應用程序之間的接口,設備驅動(dòng)程序是操作系統內核與機器硬件之間的接口。設備驅動(dòng)程序是內核的一部分,它完成以下功能:
*對設備初始化和釋放
*把數據從內核傳送到硬件和從硬件讀取數據
*讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據
*檢測和處理設備出現的錯誤
MTD(Memory Technology Device)設備是閃存芯片、小型閃存卡、記憶棒之類(lèi)的設備,它們在嵌入式設備中的使用正在不斷增加。MTD驅動(dòng)程序是在Linux下專(zhuān)門(mén)為嵌入式環(huán)境開(kāi)發(fā)的新的一類(lèi)驅動(dòng)程序。相對于常規塊設備驅動(dòng)程序,使用MTD驅動(dòng)程序的優(yōu)點(diǎn)在于他們能更好的支持、管理給予閃存設備,有基于扇區的擦除和讀/寫(xiě)操作的更好的接口。
驅動(dòng)程序結構
Linux的設備驅動(dòng)程序可以分為3個(gè)主要組成部分:
1. 自動(dòng)配置和初始化子程序,負責監測所要驅動(dòng)的硬件設備是否存在和能否正常工作。如果該設備正常,則對這個(gè)設備及其相關(guān)的設備驅動(dòng)程序需要的軟件狀態(tài)進(jìn)行初始化。這部分驅動(dòng)程序僅在初始化時(shí)被調用一次。
2. 服務(wù)于I/O請求的子程序,又稱(chēng)為驅動(dòng)程序的上半部分。調用這部分程序是由于系統調用的結果。這部分程序在執行時(shí),系統仍認為是與進(jìn)行調用的進(jìn)程屬于同一個(gè)進(jìn)程,只是由用戶(hù)態(tài)變成了核心態(tài),具有進(jìn)行此系統調用的用戶(hù)程序的運行環(huán)境,因而可以在其中調用sleep()等與進(jìn)行運行環(huán)境有關(guān)的函數。
3. 中斷服務(wù)子程序,又稱(chēng)為驅動(dòng)程序的下半部分。在Linux系統中,并不是直接從中斷向量表中調用設備驅動(dòng)程序的中斷服務(wù)子程序,而是由Linux系統來(lái)接收硬件中斷,再由系統調用中斷服務(wù)子程序。中斷可以在任何一個(gè)進(jìn)程運行時(shí)產(chǎn)生,因而在中斷服務(wù)程序被調用時(shí),不能依賴(lài)于任何進(jìn)程的狀態(tài),也就不能調用任何與進(jìn)程運行環(huán)境有關(guān)的函數。因為設備驅動(dòng)程序一般支持同一類(lèi)型的若干設備,所以一般在系統調用中斷服務(wù)子程序時(shí),都帶有一個(gè)或多個(gè)參數,以唯一標識請求服務(wù)的設備。
在系統內部,I/O設備的存/取通過(guò)一組固定的入口點(diǎn)來(lái)進(jìn)行,這組入口點(diǎn)是由每個(gè)設備的驅動(dòng)程序提供的。具體到Linux系統,設備驅動(dòng)程序所提供的這組入口點(diǎn)由一個(gè)文件操作結構來(lái)向系統進(jìn)行說(shuō)明。file_operatiON結構定義于linux/fs.h文件中。
struct file_operation{
int (*lseek)(struct inode *inode, struct file *filp, off_t off, int pos);
int (*read)(struct inode *inode, struct file *filp, char *buf, int count);
int (*write)(struct inode *inode, struct file *filp, const char *buf, int count);
int (*readdir)(struct inode *inode, struct file *filp, struct dirent *dirent, int count);
int (*select)(struct inode *inode, struct file *filp, int sel_type, select_table *wait);
int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg);
int (*mmap)(void);
int (*open)(struct inode *inode, struct file *filp);
int (*release)(struct inode *inode, struct file *filp);
int (*fasync)(struct inode *inode, struct file *filp);
};
file_operation結構中的成員幾乎全部是函數指針,所以實(shí)質(zhì)上就是函數跳轉表。每個(gè)進(jìn)程對設備的操作都會(huì )根據major、minor設備號,轉換成對file_operation結構的訪(fǎng)問(wèn)。
常用的操作包括以下幾種:
*lseek, 移動(dòng)文件指針的位置,只能用于可以隨機存取的設備。
*read, 進(jìn)行讀操作,參數buf為存放讀取結果的緩沖區,count為所要讀取的數據長(cháng)度。返回值為負表示讀取操作發(fā)生錯誤;否則,返回實(shí)際讀取的字節數。對于字符型,要求讀取的字節數和返回的實(shí)際讀取字節數都必須是inode-i_blksize的倍數。
*write, 進(jìn)行寫(xiě)操作,與read類(lèi)似
*readdir, 取得下一個(gè)目錄入口點(diǎn),只有與文件系統相關(guān)的設備程序才使用。
*select, 進(jìn)行選擇操作。如果驅動(dòng)程序沒(méi)有提供select入口,select操作會(huì )認為設備已經(jīng)準備好進(jìn)行任何I/O操作。
*ioctl, 進(jìn)行讀、寫(xiě)以外的其他操作,參數cmd為自定義的命令
*mmap, 用于把設備的內容映射到地址空間,一般只有塊設備驅動(dòng)程序使用
*open, 打開(kāi)設備準備進(jìn)行I/O操作。返回0表示打開(kāi)成功,返回負數表示失敗。如果驅動(dòng)程序沒(méi)有提供open入口,則只要/dev/driver文件存在就認為打開(kāi)成功。
*release, 即close操作。
在用戶(hù)自己的驅動(dòng)程序中,首先要根據驅動(dòng)程序的功能,完成file_operation結構中函數實(shí)現。不需要的函數接口可以直接在file_operation結構中初始化為NULL。file_operation變量會(huì )在驅動(dòng)程序初始化時(shí)注冊到系統內部。當操作系統對設備操作時(shí),會(huì )調用驅動(dòng)程序注冊的file_operation結構中的函數指針。
Linux對中斷的處理
在Linux系統里,對中斷的處理是屬于系統核心部分,因而如果設別與系統之間以中斷方式進(jìn)行數據交換,就必須把該設備的驅動(dòng)程序作為系統核心的一部分。設備驅動(dòng)程序通過(guò)調用request_irq函數來(lái)申請中斷,通過(guò)free_irq來(lái)釋放中斷。它們被定義為:
linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
評論