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 實作

編輯:Linux 教學

學習 Linux 核心模組與設備驅動,同樣從「Hello World」開始。本文示範三種在核心空間輸出訊息的方式:

  1. printk() 寫入核心日誌緩衝區(dmesg 可見)
  2. /proc 虛擬檔案系統(用戶空間 cat /proc/hello_world 讀取)
  3. /dev 字元設備檔案(用戶空間 cat /dev/hello 讀取)

並完整說明編譯環境建置、Makefile 撰寫、模組載入/卸載、udev 規則設定等實務流程。

前置準備:核心模組編譯環境

Debian/Ubuntu

$ sudo apt-get install build-essential linux-headers-$(uname -r)

Fedora/RHEL/CentOS

$ sudo dnf install kernel-devel-$(uname -r) gcc make

通用原始碼樹

$ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz
$ tar xf linux-6.6.tar.xz
$ cd linux-6.6
$ make defconfig
$ make modules_prepare
$ sudo ln -s $(pwd) /lib/modules/$(uname -r)/build

注意:模組必須對應正在運行的核心版本編譯,否則 insmod 會報錯 Invalid module format。

方式一:printk() — 最簡單的核心列印

hello_printk.c

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

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

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

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Hello World via printk");
MODULE_VERSION("0.1");

Makefile

obj-m := hello_printk.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD  := $(shell pwd)

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

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

編譯與測試

$ make
$ sudo insmod hello_printk.ko
$ dmesg -T | tail -2
[Oct 10 10:00:00] Hello, world!
[Oct 10 10:00:05] Goodbye, world!
$ sudo rmmod hello_printk

方式二:/proc 檔案 — 核心與用戶空間雙向通訊

/proc 是虛擬檔案系統,讀取時由核心回呼函數產生資料,寫入時由核心處理資料。適合「單一數值/字串」的輸出入。

hello_proc.c 關鍵片段

#include <linux/proc_fs.h>

static int hello_read_proc(char *buf, char **start, off_t off,
                           int count, int *eof, void *data) {
    char *msg = "Hello, world!\n";
    int len = strlen(msg);
    if (off > 0) return 0;          // 已讀完
    if (count < len) return -EINVAL;
    memcpy(buf, msg, len);
    *eof = 1;
    return len;
}

static int __init hello_init(void) {
    if (!create_proc_read_entry("hello_world", 0, NULL, hello_read_proc, NULL))
        return -ENOMEM;
    return 0;
}

static void __exit hello_exit(void) {
    remove_proc_entry("hello_world", NULL);
}

測試

$ sudo insmod hello_proc.ko
$ cat /proc/hello_world
Hello, world!

方式三:/dev 字元設備 — 完整的設備驅動模型

現代驅動使用 miscdevice 簡化字元設備註冊,搭配 udev 自動建立 /dev/hello 節點。

hello_dev.c 關鍵片段

#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>

static ssize_t hello_read(struct file *f, char __user *buf,
                          size_t count, loff_t *ppos) {
    char *msg = "Hello, world!\n";
    int len = strlen(msg);
    if (*ppos != 0) return 0;
    if (count < len) return -EINVAL;
    if (copy_to_user(buf, msg, len)) return -EFAULT;
    *ppos = len;
    return len;
}

static const struct file_operations hello_fops = {
    .owner = THIS_MODULE,
    .read  = hello_read,
};

static struct miscdevice hello_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = "hello",
    .fops  = &hello_fops,
};

static int __init hello_init(void) {
    return misc_register(&hello_dev);
}

static void __exit hello_exit(void) {
    misc_deregister(&hello_dev);
}

udev 規則:讓一般用戶也能讀取

建立 /etc/udev/rules.d/90-hello.rules:

KERNEL=="hello", SYMLINK+="hello_world", MODE="0444"
  • KERNEL=="hello":比對 /sys/class/misc/hello
  • SYMLINK+="hello_world":額外建立 /dev/hello_world 連結
  • MODE="0444":全域可讀
$ sudo udevadm control --reload
$ sudo rmmod hello_dev && sudo insmod hello_dev.ko
$ ls -l /dev/hello*
cr--r--r-- 1 root root 10, 57 Oct 10 10:00 /dev/hello
lrwxrwxrwx 1 root root 11 Oct 10 10:00 /dev/hello_world -> hello
$ cat /dev/hello_world
Hello, world!

三種方式比較

特性printk/proc/dev (misc)
適用場景除錯、核心事件紀錄單一數值/狀態輸出、參數調整資料流、硬體存取、權限控制
用戶空間介面dmesg / /var/log/kern.logcat /proc/xxxopen/read/write/ioctl /dev/xxx
雙向通訊否是(支援 write)是
權限控制僅 root 可看 dmesg預設 root,可改權限透過 udev 規則彈性設定
複雜度極低低中(需 file_operations)

後續學習路徑

  1. 深入 file_operations:open、write、ioctl、mmap、poll。
  2. 學習 kobject/sysfs 暴露屬性給用戶空間。
  3. 掌握併發控制:mutex、spinlock、wait_queue。
  4. 研究 platform_device、DT (Device Tree) 綁定硬體資源。
  5. 閱讀 Linux Device Drivers, 3rd Edition (LDD3) 與核心原始碼 Documentation/ 目錄。
核心模組開發的鐵律:任何在核心空間跑的代碼,一行錯誤都可能 panic 整台機器。請在虛擬機或測試機上實驗,隨時備份重要資料。
Copyright © Windows教程網 All Rights Reserved