1.分層抽象,接口與封裝
對于設備驅(qū)動程序而言,分離設備業(yè)務邏輯和底層硬件操作有利于驅(qū)動程序的擴展。而利用面向?qū)ο蟮乃枷雽︱?qū)動程序進行抽象是一個很好的方法。其主要的方法就是將驅(qū)動程序的業(yè)務邏輯中關于底層硬件操作的部分通過某種接口加以規(guī)范。如同file_operations,由此便可以使用統(tǒng)一的接口進行業(yè)務邏輯相關操作而無需關注硬件底層差異。在系統(tǒng)結構圖上來看相當于將業(yè)務邏輯作為上層實現(xiàn),而具體的硬件操作作為下層依賴,形成不同層級的系統(tǒng)結構。而關于相關接口的實現(xiàn)則交由單獨的平臺相關的程序部分加以實現(xiàn)。此外還可以通過使用簡易工廠模式對提供給業(yè)務邏輯對應接口的部分代碼加以進一步封裝。以此實現(xiàn)對于驅(qū)動程序代碼的高效封裝,復用和拓展。
(資料圖片僅供參考)
2.次設備號與一類設備
諸如tty設備與磁盤設備等大多數(shù)的設備,其硬件實體在系統(tǒng)中往往存在不僅一個實例。驅(qū)動程序往往需要維護多個設備,或者說,驅(qū)動程序應該維護驅(qū)動程序所支持的一類設備。因此,如何在系統(tǒng)中創(chuàng)建一類設備的多個實例并在驅(qū)動程序中加以辨識和管理,則是一個必須納入考量的事情。
對于Linux系統(tǒng)而言,每一個設備都有一個主設備號與次設備號,對于一個驅(qū)動程序而言,通常會在驅(qū)動程序加載的時候注冊設備并獲取主設備號,主設備號用于關聯(lián)一組文件IO操作。因此,主設備號便可以用于區(qū)分一類設備,而次設備號便可以用于區(qū)分一類設備中的不同實例。
例如一個字符設備包含有多個設備實例,可以在注冊設備后,創(chuàng)建多個設備實例。實例代碼如下
3.驅(qū)動程序中獲取次設備號
注冊設備時所綁定的一系列文件IO操作是服務于一類設備的,其包含了通用的業(yè)務方法抽象。上文指出可以通過次設備號來區(qū)分不同的設備實例,因此在接口中如何獲取次設備號則是需要討論的。
在初始化時,通過device_create創(chuàng)建設備時,我們通過MKDEV組合了主設備號與次設備號并用其創(chuàng)建了設備,在/dev目錄中我們也可以發(fā)現(xiàn)對于不同的設備,在使用ls打印時會顯示相關的主設備號和次設備號。我們可以發(fā)現(xiàn),設備號信息與設備對象是關聯(lián)的。而我們在操作設備的不同實例時恰好就是訪問了不同的設備文件,因此我們來看文件IO接口的原型。
我們可以看到,其每一個接口都至少指定了一個文件作為形參。事實上,Linux內(nèi)核提供了一個iminor方法用于獲取inode的次設備號。獲取方法如下
而對于諸如open和release方法,其形參列表中存在單獨的inode因此可以直接使用,而對于read,write等方法,則需要從其傳入的file參數(shù)中獲取inode信息。Linux內(nèi)核提供了一個file_inode方法用于提取struct file結構體的inode。
由此便可獲取當前所進行系統(tǒng)調(diào)用所訪問的設備文件的次設備號。
拓展
file_inode方法實際上返回了struct file結構體中的f_inode成員。
iminor方法返回了struct inode結構體中的i_rdev成員。
4.驅(qū)動程序的分層抽象
我們可以看到,由于多個設備實例的存在,驅(qū)動程序需要考慮的情況變得龐大。如果將對于不同設備的底層差異的判斷都交由接口所指定的對應函數(shù)實現(xiàn), 則程序體量會膨脹。并且一旦對硬件進行擴展,便要修改驅(qū)動程序的對應源碼。這使得驅(qū)動程序的開發(fā)維護變得很爛。
一個好的想法在上文中已經(jīng)提到,我們可以將文件IO接口實現(xiàn)中對于底層的操作封裝為抽象的接口,而由負責硬件的程序部分實現(xiàn)該接口,由此便完成了抽象。
因此,在驅(qū)動程序中我們可以將次設備號作為參數(shù)傳遞給相應的底層接口,只需要考慮對于這一類設備的業(yè)務邏輯即可。大大提高了代碼的復用與易擴展性。
例如,如果我們抽象一個LED的驅(qū)動程序,我們可以將LED的操作和具體的硬件實現(xiàn)分離。在對應的IO接口中僅僅實現(xiàn)對業(yè)務邏輯的包裝。在接口的實現(xiàn)中實現(xiàn)對業(yè)務邏輯的具體實現(xiàn)。
創(chuàng)建兩個文件,led_和led_,編寫Makefile。想要實現(xiàn)將多個c源碼文件編譯成一個內(nèi)核模塊文件,Makefile編寫如下。
led_負責對字符設備進行注冊,并且實現(xiàn)業(yè)務邏輯。
led_實現(xiàn)了f1c100s對于字符設備的底層實現(xiàn)。
想要實現(xiàn)對接口的定義,需要額外編寫一個頭文件led_,用于規(guī)范相關的接口。其實現(xiàn)如下
led_
led_
實現(xiàn)如下
led_
該文件主要實現(xiàn)底層的初始化,實現(xiàn)如下
5.測試程序
Copyright @ 2015-2022 中南網(wǎng)版權所有 關于我們 備案號: 浙ICP備2022016517號-4 聯(lián)系郵箱:514 676 113@qq.com