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 設備驅動入門實戰:從 Hello World 模組到 Makefile 詳解

編輯:Linux 教學

每個 Linux 驅動開發者的第一課,都是編寫一個最簡單的核心模組——「Hello World」。本文不僅給出標準範例,更詳細拆解模組生命週期、Makefile 編譯機制、核心符號表、模組參數與授權聲明等核心概念,助你建立扎實的驅動開發基石。

最小核心模組:hello.c

#include 
#include 

MODULE_LICENSE("Dual BSD/GPL");  // 授權聲明,影響核心符號可見性

static int __init hello_init(void) {
    printk(KERN_ALERT "Hello, Kernel World!\n");
    return 0;  // 非 0 表示初始化失敗,模組不會被載入
}

static void __exit hello_exit(void) {
    printk(KERN_ALERT "Goodbye, Kernel World!\n");
}

module_init(hello_init);  // 模組載入入口
module_exit(hello_exit);  // 模組卸載入口

關鍵註解宏解析

  • __init:標記初始化函式,核心載入模組後會釋放該函式佔用的記憶體(.init.text 區段)。
  • __exit:標記清理函式,若核心配置 CONFIG_MODULE_UNLOAD 未開啟,該函式會被編譯器優化移除。
  • module_init/exit:註冊模組入口/出口點,展開為對應區段的函式指標。

跨平台編譯 Makefile 詳解

驅動模組編譯需依賴核心原始碼樹的 Kbuild 系統。以下為 ARM 交叉編譯環境範例:

# 核心原始碼樹路徑(已配置並編譯過的)
KERNELDIR := /home/user/linux-5.10

# 當前模組源碼目錄
PWD := $(shell pwd)

# 交叉編譯工具鏈前綴
CROSS_COMPILE := arm-linux-gnueabihf-
CC := $(CROSS_COMPILE)gcc

# 目標模組名稱(hello.c -> hello.ko)
obj-m := hello.o

# 若模組由多個 .c 組成:
# obj-m := mydrv.o
# mydrv-objs := file1.o file2.o

all:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
	rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers

install:
	cp hello.ko /path/to/rootfs/lib/modules/$(shell uname -r)/extra/
	depmod -a

Makefile 關鍵變數解析

  • KERNELDIR:指向核心源碼樹頂層,內含 Makefile 與 scripts/。
  • M=$(PWD):告知核心建置系統模組源碼位置(外部模組模式)。
  • obj-m:指定生成可載入模組(.ko),對應 .c 檔名。
  • CROSS_COMPILE:交叉編譯工具鏈前綴,make 會自動拼接 gcc, ld, strip 等工具。

模組載入/卸載實戰驗證

# 編譯
$ make
# 輸出 hello.ko

# 部署至目標板(NFS/SCP/USB)
$ scp hello.ko root@target:/lib/modules/$(uname -r)/extra/

# 目標板載入
root@target:~# insmod hello.ko
Hello, Kernel World!

# 查看已載入模組
root@target:~# lsmod | grep hello
hello        16384  0

# 卸載模組
root@target:~# rmmod hello
Goodbye, Kernel World!

核心模組開發十大核心觀念

  1. 運行於核心空間: 無 libc、無標準輸出、無保護機制,Bug 直接導致 Kernel Panic。
  2. 資源管理責任自負: init 申請的資源(記憶體、IRQ、I/O 區域、中斷),必須在 exit 中完整釋放,否則資源洩漏需重開機恢復。
  3. 特權級隔離: x86 Ring 0 (核心) vs Ring 3 (使用者),ARM EL1 vs EL0。系統呼叫是受控跨越邊界的唯一通道。
  4. 並發無處不在: SMP、中斷、核心搶佔、預讀執行緒,共享資料必須加鎖保護。
  5. 雙底線函式慎用: 如 __kmalloc, __init_waitqueue_head 通常為內部實現,介面不穩定,優先使用公開 API。
  6. 核心禁用浮點運算: 需顯式保存/恢復 FPU 狀態 (kernel_fpu_begin/end),極度不建議在核心使用浮點。
  7. 模組授權聲明強制: MODULE_LICENSE("GPL") 才能使用 EXPORT_SYMBOL_GPL 導出的符號(如 mutex_lock)。
  8. 符號導出機制: 模組間共享符號需用 EXPORT_SYMBOL(name) 或 EXPORT_SYMBOL_GPL(name),必須置於全域變數區。
  9. 核心參數傳遞: module_param(name, type, perm) 允許載入時傳參(insmod mod.ko param=value)。
  10. 標準頭文件雙雄: <linux/init.h> (init/exit 宏) + <linux/module.h> (核心模組核心定義)。

從 Hello World 邁向真實驅動

掌握模組編譯、載入、參數傳遞、日誌輸出、資源管理後,下一步即是註冊字元裝置(cdev_add)、實現 file_operations(open/read/write/ioctl)、申請 I/O 記憶體與中斷號,逐步構建完整的字元裝置驅動。每一行核心代碼都在邊界上行走,謹慎、測試、再測試,是驅動開發者的基本功。

Copyright © Windows教程網 All Rights Reserved