天天看點

Linux裝置模型 (4)module的建立module的撤銷

(注:本文的分析基于2.6.36核心)

當module被insmod到核心空間時,/sys/module目錄下會相應建立一個和子產品同名的目錄。我們以usb_storage為例,在執行完sudo modprobe usb_storage之後,sysfs裡會産生一個名為usb_storage的目錄,其目錄結構是:

stat64("/sys/module/usb_storage", 0xbfb9a654) = -1 ENOENT (No such file or directory) open("/lib/modules/2.6.35-24-generic/kernel/drivers/usb/storage/usb-storage.ko", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=94776, ...}) = 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)                           = ?

從這個流程我們可以看到,insmod在執行時,首先會把module的内容映射到記憶體裡,然後呼叫系統調用init_module來實作真正的工作。

如上圖所示,這是系統調用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, xxx)來定義,但一般情況下由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: Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)

相應的,在/sys/module/usb_storage/notes目錄下建立的notes檔案就是.note.gnu.build-id。

上面的7條流程裡,并無建立drivers的地方,那/sys/module/usb_storage下的drivers目錄是如何建立的呢?答案在下圖:

在usb_storage的module_init中,會調用usb_register來注冊usb_driver結構,如圖中所示,最終會調用module_add_driver來建立drivers目錄。

module的撤銷過程和前文中的建立過程一一對應,在這裡就不詳細叙述了,請看下圖。

關于sysfs中的其他子目錄的建立和撤銷,大家也可以很容易的在Linux核心中找到對應的代碼,本文不再一一贅述。

繼續閱讀