Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 核心模塊開發入門:初始化/清理函數、模塊授權與 printk 等級機制實作

編輯:Linux 教學

前言

Linux 核心模塊允許動態載入/卸載程式碼,避免單一巨大核心映像。本文從最簡單的 Hello World 切入,詳細解析 module_init/exit、MODULE_LICENSE 等巨集用法,並深入探討 printk 8 級優先權、控制台輸出門檻與動態除錯開關技巧,為驅動開發打穩基礎。

一、最小模塊範例


/* hello.c */
#include 
#include 

static int __init hello_init(void) {
    printk("Hello, kernel module!\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk("Goodbye, kernel module!\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_VERSION("1.0");

建置與測試


# Makefile
obj-m += hello.o
KDIR := /lib/modules/$(shell uname -r)/build
all:
    make -C $(KDIR) M=$(PWD) modules
clean:
    make -C $(KDIR) M=$(PWD) clean

# 編譯載入
make
insmod hello.ko
dmesg | tail   # 觀看 printk 輸出
rmmod hello

二、初始化與清理函數深度解析

屬性初始化函數清理函數
巨集module_init(fn)module_exit(fn)
調用時機insmod 載入時rmmod 卸載時
回傳值0 成功、負錯誤碼失敗(載入中止)void
static建議加,限制連結可見性建議加
__init / __exit載入後釋放該段記憶體(節省 RAM)內建核心時自動捨棄
必要性必須必須(無清理函數無法載入)

三、模塊描述性巨集


MODULE_LICENSE("GPL");        // 必填,否則標記 taint
MODULE_AUTHOR("Name");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("Brief");
MODULE_ALIAS("alias_name");   // modprobe 別名

四、printk 優先權機制完整圖解

1. 8 級優先權定義

巨集數值含義
KERN_EMERG0系統不可用
KERN_ALERT1需立即處理
KERN_CRIT2嚴重錯誤
KERN_ERR3錯誤
KERN_WARNING4警告(printk 預設)
KERN_NOTICE5正常但重要
KERN_INFO6資訊
KERN_DEBUG7除錯訊息

2. 控制台輸出門檻

只有優先權數值 ≤ console_loglevel 的訊息才會輸出到實體控制台。
預設值查看/修改:


cat /proc/sys/kernel/printk
# 輸出四值:console_loglevel  default_message_loglevel  minimum_console_loglevel  default_console_loglevel
# 典型預設:7 4 1 7  → console_loglevel=7 (KERN_DEBUG 也會顯示)

# 臨時調整(需 root)
echo 8 > /proc/sys/kernel/printk   # 讓所有等級含 KERN_DEBUG 皆顯示

3. 實驗驗證


printk("no level\n");           // 預設 KERN_WARNING (4) → 會顯示
printk(KERN_DEBUG "debug\n");   // 等級 7 → 預設 console=7 會顯示
printk("<7>debug explicit\n");   // 同 KERN_DEBUG

若 console_loglevel=6,則 KERN_DEBUG (7) 不會在控制台顯示,但永遠會寫入 /var/log/messages(由 klogd/rsyslog 收集)。

五、動態除錯開關技巧


#define DEBUG_ENABLE 1

#if DEBUG_ENABLE
#define P_DEBUG(fmt, ...) printk(KERN_INFO "[%s] " fmt, __func__, ##__VA_ARGS__)
#else
#define P_DEBUG(fmt, ...) printk(KERN_DEBUG "[%s] " fmt, __func__, ##__VA_ARGS__)
#endif

static int __init test_init(void) {
    P_DEBUG("Debug message %d\n", 123);  // 依 DEBUG_ENABLE 決定是否進控制台
    return 0;
}

編譯時切換 DEBUG_ENABLE 即可控制除錯訊息是否輸出到控制台,無需修改大量 printk 呼叫。

六、常見坑點

  • 忘寫 MODULE_LICENSE → 核心標記 tainted,部份符號(如 EXPORT_SYMBOL_GPL)不可用。
  • 初始化函數回傳非 0 → insmod 失敗,dmesg 顯示錯誤碼。
  • 清理函數缺失 → 核心拒絕載入模塊。
  • printk 格式字串:核心不支援 %f 浮點,整數用 %d/%ld,指標用 %p(會自動哈希保護位址)。
Copyright © Windows教程網 All Rights Reserved