針對 ARM 架構(AT91RM9200)的 Linux 2.6.12 內核,本文演示從原始碼編寫、交叉編譯、目標板部署到動態載入/卸載的完整內核模組開發流程,適用於嵌入式 Linux 驅動開發入門。
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 符號。
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=。
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]=...
testmodule.ko 複製至開發板 /root/ 或 /lib/modules/2.6.12/kernel/drivers/。chmod 644 testmodule.ko(+x 非必要,模組非可執行檔)。insmod testmodule.kodmesg | tail -2Hello! This is the first test module!lsmod | grep testmodulecat /proc/modules | grep testmodulemodinfo testmodule.kormmod testmoduledmesg | tail -1Module 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 | 工具鏈路徑未加入 PATH | export 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 平台上高效開發、部署與維護內核模組,為驅動開發奠定堅實基礎。