《linux裝置模型 (2)》和《linux裝置模型 (3)》主要通過一些簡單的實作介紹了kobject、kset、kobj_type、attribute等資料結構的用法,但這些實作並沒有涉及到實際環境下的裝置模型和sysfs。本文將以/sys下的module子目錄為例,看看核心是如何構建sysfs這棵大樹的。
(注:本文的分析基於2.6.36核心)
當module被insmod到核心空間時,/sys/module目錄下會相應建立乙個和模組同名的目錄。我們以usb_storage為例,在執行完sudo modprobe usb_storage之後,sysfs裡會產生乙個名為usb_storage的目錄,其目錄結構是:
在linux 2.6核心裡,module的插入是由使用者程式insmod(modprobe最終也是呼叫insmod)發起的,但大部分工作還是由核心完成。我們可以用strace來觀察一下insmod的流程。
stat64("/sys/module/usb_storage", 0xbfb9a654) = -1 enoent (no such file or directory)從這個流程我們可以看到,insmod在執行時,首先會把module的內容對映到記憶體裡,然後呼叫系統呼叫init_module來實現真正的工作。open("/lib/modules/2.6.35-24-generic/kernel/drivers/usb/storage/usb-storage.ko", o_rdonly) = 3
fstat64(3, ) = 0
mmap2(null, 94776, prot_read|prot_write, map_private, 3, 0) = 0xb776f000
close(3) = 0
init_module(0xb776f000, 94776, "") = 0
munmap(0xb776f000, 94776) = 0
exit_group(0) = ?
如上圖所示,這是系統呼叫init_module的執行路徑。因為本文只是討論裝置模型和sysfs,流程圖裡只涉及到相關的內容。
1、mod_sysfs_init首先會查詢當前模組(本例中是usb_storage)在sysfs中是否已經存在,如果沒有,則呼叫kobject_init_and_add建立之;
2、呼叫kobject_create_and_add建立holders目錄。holders目錄用於存放指向其他module的鏈結,這裡的其他module都是依賴於當前module的。以usb_storage為例,如果我們需要使用ums_xx模組(比如ums_karma或者ums_freecom等),可以呼叫sudo modprobe ums_xx來完成載入,因為ums_xx依賴於usb_storage,所以在usb_storage/holders目錄下就會建立指向ums_xx的鏈結,同時refcnt也會加1;
3、module_param_sysfs_setup用來建立parameters目錄,這個目錄裡的檔案對應著當前module的所有引數。在linux核心裡,module的二進位制ko檔案中的__param section用來儲存當前module的引數,load_module會把這些引數讀取到記憶體結構裡,module_param_sysfs_setup再根據相應的結構來建立paramters目錄及其引數檔案;
4、module_add_modinfo_attrs用來建立當前module目錄下的4個檔案:version、srcversion、refcnt和initstate,其中version和srcversion的資訊儲存在二進位制ko檔案的.modinfo section裡。對於usb_storage模組來說,並沒有指定version,所以不存在version這個檔案。順便羅嗦一句,在linux核心裡,可以用巨集module_version定義版本號,比如module_version("v1.00")定義版本號為v1.00,這裡的版本資訊完全是字串,並無特定格式。srcversion可以由module_info(srcversion, ***)來定義,但一般情況下由modpost預設生成就可以了。refcnt反映當前module的引用計數。initstate反映module的三種狀態:live、coming和going;
5、add_usage_links和holders是密切相關的,但這個函式並不是操作當前module的holders目錄。以ums_xx為例,在ums_xx的載入過程中,其add_usage_links會把自己作為鏈結加到usb_storage的holders目錄下;
6、sections目錄對應當前module的二進位制ko檔案裡的section資訊,這是通過add_sect_attrs實現的。需要提醒一下的是,section的命名通常以「.」開頭,而以「.」開頭的檔案在linux裡被認為是隱藏檔案,所以如果要察看的話要在ls命令後加"-a"引數,下面談到的notes同樣需要這樣處理;
7、add_notes_attrs用來建立notes目錄。elf檔案格式定義了一種名為note的元素,主要用於給二進位制檔案新增一些標示資訊。通常,我們可以用readelf來察看elf檔案是否包含note section。比如usb_storage,我們可以使用命令「readelf usb-storage.ko -n」察看,其輸出如下:
notes at offset 0x00000034 with length 0x00000024:相應的,在/sys/module/usb_storage/notes目錄下建立的notes檔案就是.note.gnu.build-id。owner data size description
gnu 0x00000014 nt_gnu_build_id (unique build id bitstring)
上面的7條流程裡,並無建立drivers的地方,那/sys/module/usb_storage下的drivers目錄是如何建立的呢?答案在下圖:
在usb_storage的module_init中,會呼叫usb_register來註冊usb_driver結構,如圖中所示,最終會呼叫module_add_driver來建立drivers目錄。
module的撤銷過程和前文中的建立過程一一對應,在這裡就不詳細敘述了,請看下圖。
關於sysfs中的其他子目錄的建立和撤銷,大家也可以很容易的在linux核心中找到對應的**,本文不再一一贅述。
4 linux匯流排裝置驅動模型
1 分層分離的概念。這種思想的優點就是能把很多檔案共用的 抽離集中起來成為乙個或者多個核心檔案供裝置相關層呼叫,每一層專注於自己的功能。分離 把硬體相關的 和驅動 穩定的 分離開來,即要編寫兩個檔案 dev.c和drv.c 2 bus dev drv模型的匹配規則 核心發現乙個裝置時,呼叫devic...
Linux裝置模型
linux裝置驅動模型 我們在寫最簡單的裝置驅動程式的時候,我們將所有的硬體資訊都儲存在了驅動 中,這樣有乙個非常明顯的不足 會導致驅動程式的通用性極差,一旦硬體平台或硬體連線有鎖改變,就一定要修改驅動 為了解決這個問題,linux在2.6版本之後,新增了 匯流排 裝置 驅動 的linux裝置模型,...
linux裝置模型
linux核心的整體架構 linux裝置模型 linux裝置模型 1 基本概念 linux裝置模型 2 kobject linux裝置模型 3 uevent linux裝置模型 4 sysfs linux裝置模型 5 device和device driver linux裝置模型 6 bus linu...