萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux 2.6.12 內核模組開發入門:交叉編譯、載入與除錯完整流程

針對 ARM 架構(AT91RM9200)的 Linux 2.6.12 內核,本文演示從原始碼編寫、交叉編譯、目標板部署到動態載入/卸載的完整內核模組開發流程,適用於嵌入式 Linux 驅動開發入門。

開發環境準備

  • 目標平台:AT91RM9200 (ARM920T),運行 Linux 2.6.12。
  • 交叉編譯工具鏈:arm-linux-gcc (3.4.1),安裝路徑 /src/3.4.1/bin/。
  • 內核原始碼:/src/linux-2.6.12,必須與目標板運行內核版本完全一致,否則模組版本魔數不匹配導致 insmod 失敗。

步驟一:編寫最簡內核模組 testmodule.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

static int __init hello_init(void) {
    printk(KERN_INFO "Hello! This is the first test module!\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "Module exit! Bye Bye!\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Developer");
MODULE_DESCRIPTION("Simple test module for AT91RM9200");

關鍵點:
- __init/__exit 標記讓內核在初始化/清理後釋放對應代碼段記憶體。
- printk 使用 KERN_INFO 日誌等級,輸出至內核環形緩衝區,dmesg 可見。
- MODULE_LICENSE("GPL") 宣告授權,避免「taints kernel」警告並允許使用 GPL-only 符號。

步驟二:編寫 Kbuild 風格 Makefile

obj-m := testmodule.o
KDIR := /src/linux-2.6.12
PWD  := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

注意:$(MAKE) 前必須為 Tab 字元,非空白鍵。SUBDIRS 在 2.6 內核為標準變數,5.x 內核改為 M=。

步驟三:交叉編譯生成 .ko 檔案

cd /path/to/module/source
make CC=/src/3.4.1/bin/arm-linux-gcc
# 成功產出 testmodule.ko
file testmodule.ko
# 輸出:ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), BuildID[sha1]=...

步驟四:目標板部署與動態載入測試

  1. 傳輸:透過 TFTP/NFS/串口 (sz/rz) 將 testmodule.ko 複製至開發板 /root/ 或 /lib/modules/2.6.12/kernel/drivers/。
  2. 權限:chmod 644 testmodule.ko(+x 非必要,模組非可執行檔)。
  3. 載入:
    insmod testmodule.ko
    dmesg | tail -2
    預期輸出:
    Hello! This is the first test module!
  4. 驗證模組狀態:
    lsmod | grep testmodule
    cat /proc/modules | grep testmodule
    modinfo testmodule.ko
  5. 卸載:
    rmmod testmodule
    dmesg | tail -1
    預期輸出:Module exit! Bye Bye!

常見錯誤與排除

錯誤現象原因解決方案
insmod: ERROR: could not insert module: Invalid module format內核版本/配置不匹配(vermagic 不符)確保 KDIR 指向與目標板完全相同的內核源碼,並使用相同 .config 編譯內核
Unknown symbol in module使用了未導出符號或 GPL-only 符號但模組非 GPL檢查 /proc/kallsyms 確認符號導出;添加 MODULE_LICENSE("GPL")
insmod: ERROR: could not insert module: Operation not permitted內核啟用 CONFIG_MODULE_SIG_FORCE 強制簽名簽名模組或關閉內核簽名強制
編譯錯誤 arm-linux-gcc: not found工具鏈路徑未加入 PATHexport PATH=/src/3.4.1/bin:$PATH 或 Makefile 指定絕對路徑

進階擴展方向

  • 參數傳遞:module_param(name, type, perm) 支援啟動時動態配置。
  • 字符/區塊設備驅動:cdev_init、register_chrdev_region、file_operations 實作 open/read/write/ioctl。
  • 平台設備模型:platform_driver/platform_device、Device Tree 綁定、of_match_table。
  • 中斷處理:request_irq、tasklet/workqueue 下半部處理。
  • 除錯技巧:kgdb 串口遠端除錯、ftrace/trace-cmd 函數追蹤、crash 核心轉儲分析。

掌握交叉編譯環境一致性、Kbuild 系統運作、模組生命週期管理,即可在嵌入式 Linux 平台上高效開發、部署與維護內核模組,為驅動開發奠定堅實基礎。

copyright © 萬盛學電腦網 all rights reserved