1. 程式人生 > >模塊機制

模塊機制

工具 建立 如果 其他 允許 上下 from sig 數據拷貝

模塊是內核的一部分(通常是設備驅動程序),按需動態裝入模塊可以保證內核達到最小並且使內核非常靈活。一旦裝入一個Linux內核模塊,那麽它就像任何標準的內核代碼一樣成為內核的一部分,具有相同的權限和職責。一方面凡是由內核“移出”的所有符號都可以在模塊中引用;另一方面,除了這個特意移出的符號及系統調用外,應用程序別無途徑直接訪問內核中的資源。

在應用程序界面上,內核通過4個系統調用支持可安裝模塊的動態安裝和拆卸,它們是create_module(),init_module(),query_module(),以及delete_module()。通常,用戶不需要直接跟這些系統調用大交道,而可以用系統提供的工具/sbin/insmod(插入模塊)和/sbin/rmmode(移走模塊)來安裝和拆卸模塊。當然,這兩個工具最終還是要通過這些系統調用完成有關操作的。/sbin/insmod 所調用的函數流程如圖所示:

技術分享圖片

內核空間和用戶空間

普通程序和內核模塊的不同:對於模塊的可執行代碼時目標代碼,缺少了一個連接過程——而insmod程序完成了這個連接過程。

技術分享圖片

1 處理器保護級

在i386處理器上實現了四層保護級別,依次是0級、1級、2級和3級,其中0級特權最高,3級特權最低。無論何時處理器總是在一個級別上運行。如果需要訪問高特權級別的存儲空間,只能通過由處理器規定的一些特權門完成操作。一般在0級運行的是操作系統的內核部分;在3級運行的是應用程序部分。在最低級運行的時候,操作系統禁止對硬件的直接訪問和對內核運行內存空間的未授權訪問。

2 用戶空間和內核空間權限

對應於在0級別運行的內核程序,它所在的內存空間是內核空間;對應於在3級運行的應用程序,它所指的內存空間是用戶空間。Linux通過系統調用或硬件中斷完成從用戶到內核空間的轉換。在進程上下文中執行系統調用的內核代碼,系統調用就可以訪問原來進程的上下文數據。

對中斷來說,它並不存在於任何進程上下文中,而是由內核來運行的。對模塊來說,它就是在系統的用戶空間定義的,然後通過用戶空間的程序insmod將它插入到內核空間中運行,可以像真正的內核一樣充分利用0級特權的功能執行程序。從圖可以看出,insmod通過create_module()和init_module()兩個系統調用將一個模塊運行的空間從用戶級切換到內核級。rmmod通過delete_module()系統調用將一個模塊從內核空間中移出。

3 內核態和用戶態之間數據傳遞

在內核空間與用戶空間存在數據的傳遞,下面的函數與宏定義在內核中對這種傳遞進行操作。

函數copy_to_user從內核空間把數據拷貝到用戶空間,拷貝成功返回0,否則,返回不能被拷貝的字節數。其參數to表示在用戶空間的目標地址,參數from是在內核空間的源地址,參數n是需要拷貝數據的長度。函數原型如下:

unsigned long copy_to_user(void __user *to,const void *from,unsigned long n);

函數copy_from_user從用戶空間拷貝一塊數據,參數to表示在內核空間的目標地址,參數from是在用戶空間的源地址,參數n是需要拷貝數據的長度。拷貝成功返回0,否則,返回不能被拷貝的字節數。如果有些數據沒拷貝,函數copy_from_user將填充0到請求的長度n,函數copy_from_user原型如下:

unsigned long copy_from_user(void *to,const void __user *from,unsigned long n);

模塊的使用過程

模塊的使用過程如下:

打開待安裝模塊並將其讀入到用戶空間,所謂“模塊”就是經過編譯但未經連接的.o文件。

模塊中有一些在模塊內部無法落實的符號(函數名或變量名),這些符號的引用必須連接到內核中的相應符號,也就是必須把這些符號在內核映像中的地址填入模塊中需要訪問這些符號的指令,以及數據結構中。為此,需要通過系統調用query_module()函數向內核詢問這些符號在內核中的地址。如果內核允許“移出”這些符號的地址,就會返回有關的“符號表”。有些符號可能並不屬於內核本身,而屬於已經安裝的其他模塊。

取得了內核“移出”的符號表“以後,模塊中所有的符號引用就得到落實。這部分操作與編譯後的連接相似。不過,常規的”連接“常常是雙向的,而現在只是在模塊中引用內核裏的符號或者某些已經安裝的模塊中的符號,而內核不能反過來引用這個待安裝模塊中的符號。從這個意義上說,模塊與內核的連接時單向連接。

通過系統調用sys_init_module(),把用戶空間中模塊目標文件解析後裝入內核空間,建立在sysfs文件系統中的模塊對象,再調用模塊中一個名為init_module()的函數。每個模塊的init_module()函數負責向內核”登記”本模塊的一些包含著函數指針的數據結構。完成這種登記後,模塊與內核之間的連接(另一個方向上的連接)才算真正完成。

模塊機制