如何寫Linux字符設(shè)備驅(qū)動(dòng)?首先我們來分解一下字符設(shè)備驅(qū)動(dòng)都有那些結(jié)構(gòu)或者方法組成,也就是說實(shí)現(xiàn)一個(gè)可以使用的字符設(shè)備驅(qū)動(dòng)我們必須做些什么工作。
1、主設(shè)備號(hào)和次設(shè)備號(hào)
對(duì)于字符設(shè)備的訪問是通過文件系統(tǒng)中的設(shè)備名稱進(jìn)行的。他們通常位于/dev目錄下。如下:
其中b代表塊設(shè)備,c代表字符設(shè)備。對(duì)于普通文件來說,ls -l會(huì)列出文件的長度,而對(duì)于設(shè)備文件來說,上面的7,5,4等代表的是對(duì)應(yīng)設(shè)備的主設(shè)備號(hào),而后面的0,1,2,10等則是對(duì)應(yīng)設(shè)備的次設(shè)備號(hào)。那么主設(shè)備號(hào)和次設(shè)備號(hào)分別代表什么意義呢?一般情況下,可以這樣理解,主設(shè)備號(hào)標(biāo)識(shí)設(shè)備對(duì)應(yīng)的驅(qū)動(dòng)程序,也就是說1個(gè)主設(shè)備號(hào)對(duì)應(yīng)一個(gè)驅(qū)動(dòng)程序。當(dāng)然,現(xiàn)在也有多個(gè)驅(qū)動(dòng)程序共享主設(shè)備號(hào)的情況。而次設(shè)備號(hào)有內(nèi)核使用,用于確定/dev下的設(shè)備文件對(duì)應(yīng)的具體設(shè)備。舉一個(gè)例子,虛擬控制臺(tái)和串口終端有驅(qū)動(dòng)程序4管理,而不同的終端分別有不同的次設(shè)備號(hào)。
1.1、設(shè)備編號(hào)的表達(dá)
在內(nèi)核中,dev_t用來保存設(shè)備編號(hào),包括主設(shè)備號(hào)和次設(shè)備號(hào)。在2.6的內(nèi)核版本種,dev_t是一個(gè)32位的數(shù),其中12位用來表示主設(shè)備號(hào),其余20位用來標(biāo)識(shí)次設(shè)備號(hào)。
通過dev_t獲取主設(shè)備號(hào)和次設(shè)備號(hào)使用下面的宏:
MAJOR(dev_t dev);
MINOR(dev_t dev);
相反,通過主設(shè)備號(hào)和次設(shè)備號(hào)轉(zhuǎn)換為dev_t類型使用:
MKDEV(int major, int minor);
1.2、分配和釋放設(shè)備編號(hào)
在構(gòu)建一個(gè)字符設(shè)備之前,驅(qū)動(dòng)程序首先要獲得一個(gè)或者多個(gè)設(shè)備編號(hào),這類似一個(gè)營業(yè)執(zhí)照,有了營業(yè)執(zhí)照才在內(nèi)核中正常工作營業(yè)。完成此工作的函數(shù)是:
int register_chrdev_region(dev_t first, unsigned int count, const char *name);
first是要分配的設(shè)備編號(hào)范圍的起始值。count是連續(xù)設(shè)備的編號(hào)的個(gè)數(shù)。name是和該設(shè)備編號(hào)范圍關(guān)聯(lián)的設(shè)備名稱,他將出現(xiàn)在/proc/devices和sysfs中。此函數(shù)成功返回0,失敗返回負(fù)的錯(cuò)誤碼。此函數(shù)是在已知主設(shè)備號(hào)的情況下使用,在未知主設(shè)備號(hào)的情況下,我們使用下面的函數(shù):
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, const char* name);
dev用于輸出申請(qǐng)到的設(shè)備編號(hào),firstminor要使用的第一個(gè)此設(shè)備編號(hào)。
在不使用時(shí)需要釋放這些設(shè)備編號(hào),已提供其他設(shè)備程序使用:
void unregister_chrdev_region(dev_t dev, unsigned int count);
此函數(shù)多在模塊的清除函數(shù)中調(diào)用。
分配到設(shè)備編號(hào)之后,我們只是拿到了營業(yè)執(zhí)照,雖說現(xiàn)在已經(jīng)準(zhǔn)備的差不多了,但是我們只是從內(nèi)核中申請(qǐng)到了設(shè)備號(hào),應(yīng)用程序還是不能對(duì)此設(shè)備作任何事情,我們需要一個(gè)簡單的函數(shù)來把設(shè)備編號(hào)和此設(shè)備能實(shí)現(xiàn)的功能連接起來,這樣我們的模塊才能提供具體的功能.這個(gè)操作很簡單,稍后就會(huì)提到,下一篇我們?cè)賮斫榻B幾個(gè)重要的數(shù)據(jù)結(jié)構(gòu)。