2014年9月24日 星期三

最簡單的 Kernel module : Hello world kernel module

        本篇記錄如何建立一個最簡單的 Kernel module : 也就是 Hello world kernel module,總共只包含了兩個函式,一個在 module 載入時被呼叫,另一個則是在卸載時被呼叫。

        首先先來撰寫 kHelloWorld.c ,程式碼如下:
// kHelloWorld.c
// A simple kernel module

#include <linux/module.h>   // Needed by all modules
#include <linux/init.h>     // Needed for module_init and module_exit

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jay Lin <mrlemon01@gmail.com>");

// Define these functions before module_init and module_exit macros.
static int hello_init(void)
{
    printk(KERN_ALERT "Hello world\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye world\n");
}

module_init(hello_init);    // Replace init_module()
module_exit(hello_exit);    // Replace cleanup_module()

        <linux/module.h> 為任何 module 都必須引入的標頭檔。

        所有的 module 至少都需要包含兩個函式,分別是 init_module() 及 cleanup_module() ,用於載入時的初始化以及卸載時的清理動作,而這裡使用 <linux/init.h> 所提供的巨集 module_init 及 module_exit ,讓我們使用不同名稱的函式作為載入函式及卸載函式。注意這兩個巨集須寫在函式定義之後。

        printk 函式用於 kernel 的日誌傾印 (log) ,所以在此範例中的兩個函式有順利被呼叫的話,可以使用 dmesg 指令看到傾印的訊息。 KERN_ALERT 代表傾印的等級,可以從 <linux/kern_levels.h> 中找到各個等級的定義 ( 有些 linux 版本放置在 <linux/kernel.h> )。

        接著來撰寫一個最簡單的 Makefile 並編譯他:
obj-m := kHelloWorld.o

        執行指令 make -C /usr/src/linux-`uname -r` M=`pwd` modules 編譯產生 ko 檔。

        接著執行指令 insmod ./kHelloWorld.ko 載入 module,載入過程中可能不會顯示任何的文字提示,是因為 printk 主要用於記錄日誌,所以不一定會顯示到主控台畫面上,此時可以使用 dmesg 確認日誌的紀錄訊息。

        如果要確認 module 是否有被載入,也可以使用 lsmod 指令列出現在已載入的所有 module。最後使用 rmmod 將 module 卸載,使用 dmesg 和 lsmod 確認是否成功卸載吧!

沒有留言:

張貼留言