編寫簡單的Linux2.6核心模組(1)

來源:互聯網
上載者:User

您的核心必須已經啟用這些選項進行了編譯:

Loadable module support  --->  [*] Enable loadable module support  [*]   Module unloading  [ ]   Module versioning support (EXPERIMENTAL)  [*]   Automatic kernel module loading

如果按照第一篇教程中的說明編譯核心,那麼就已經正確地設定了這些選項。否則,修改這些選項,重新編譯核心,並引導到新核心。

一個簡單的模組骨架

首先,找到編譯當前 Linux 核心的原始碼。將目錄切換到 Linux 原始碼目錄中的 drivers/misc/。現在,拷貝下面的代碼並將其粘貼到一個名為 mymodule.c 的檔案:

#include #include #include static int __init mymodule_init(void){    printk ("My module worked!\n");    return 0;}static void __exit mymodule_exit(void){    printk ("Unloading my module.\n");    return;}module_init(mymodule_init);module_exit(mymodule_exit);MODULE_LICENSE("GPL");
儲存這個檔案,並在同一目錄下編輯 Makefile 檔案。添加這一行:

obj-m += mymodule.o
編譯模組:

# make -C  SUBDIRS=$PWD modules
使用 insmod ./mymodule.ko 載入這個模組,並查看是否列印了您的訊息: dmesg | tail。應該會在輸出的結束處看到:

My module worked!
現在刪除核心模組: rmmod mymodule。再次查看 dmesg;應該會看到:

Unloading my module.
這樣您就已經編寫並運行了一個新的核心模組!恭喜!

模組/核心介面

現在,我們來做一些與您的模組有關的更有趣的事情。要瞭解的一個關鍵內容是,模組只能“看到”核心故意讓它訪問的函數和變數。首先,我們以錯誤的方式來進行嘗試。

編輯檔案 kernel/printk.c,在所有包含檔案之後其他全域變數聲明附近但要在所有函數之外)添加下面一行:

int my_variable = 0;
現在重新編譯核心並引導到新核心。然後,將下面的內容添加到模組的 mymodule_init 函數起始處,置於其他代碼之前。

extern int my_variable;printk ("my_variable is %d\n", my_variable);my_variable++;
儲存修改並重新編譯模組:

# make -C  SUBDIRS=$PWD modules
載入模組這將失敗): insmod ./mymodule.ko。模組的載入會失敗,並給出訊息:

insmod: error inserting './mymodule.ko': -1 Unknown symbol in module
這說明核心不允許模組訪問那個變數。當模組載入時,它必須解析所有外部參考,比如函數名或者變數名。如果它不能找到核心匯出的符號列表中所有未解析的名稱,那麼模組就不能寫入那個變數或者調用那個函數。在核心中某個地方有為變數 my_variable 分配的空間,但模組不知道是哪裡。

為解決此問題,我們將把 my_variable 添加到核心匯出的符號列表中。在很多核心目錄中,都有一個特定的檔案,用於匯出在那個目錄中定義的符號。再次開啟 kernel/printk.c 檔案,在變數聲明之後添加下面一行:

EXPORT_SYMBOL(my_variable);
重新編譯並重新引導到新核心。現在再一次嘗試載入模組: insmod ./mymodule.ko。這一次,當查看 dmesg 時,應該看到:

my_variable is 0My module worked!
重新載入模組:

# rmmod mymodule && insmod ./mymodule.ko
現在應該看到:

Unloading my module.my_variable is 1My module worked!
每次重新載入那個模組, my_variable 都會增 1。您正在讀寫一個在主核心中定義的變數。只要被 EXPORT_SYMBOL() 顯式地聲明,模組就可以訪問主核心中的任何變數。例如,函數 printk() 是在核心中定義的,並且在檔案 kernel/printk.c 中被匯出。

簡單的可引導核心模組是用來研究核心的一個有趣的途徑。例如,可以使用一個模組來開啟或關閉 printk,方法是在核心中定義一個變數 do_print它初始化為 0)。然後,讓所有 printk 都依賴於“do_print”:

if (do_print) {    printk ("Big long obnoxious message\n");}
然後,只有當您的模組被載入時才開啟它。

模組參數

引導模組時,可以向它傳遞參數。要使用模組參數載入模組,這樣寫:

insmod module.ko [param1=value param2=value ...]
為了使用這些參數的值,要在模組中聲明變數來儲存它們,並在所有函數之外的某個地方使用宏 MODULE_PARM(variable, type)MODULE_PARM_DESC(variable, description) 來接收它們。 type 參數應該是一個格式為 [min[-max]]{b,h,i,l,s} 字串,其中 min 和 max 是數組的長度限度。如果兩者都忽略了,則預設為 1。最後一個字元是類型說明符:

b       byteh       shorti       intl       longs       string

可以在 MODULE_PARM_DESCdescription 域中添加任何需要的說明符。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.