Linux驅動開發(一):字符設備

目的:實現最簡單的點燈操作。

Linux一切皆文件,應用程序訪問某個物理設備(文件)時,首先通過open, read, write等庫函數調用系統調用接口(System call interface),系統調用通過傳進來的系統調用號操作虛擬文件系統(Virtual File System),VFS再根據目標文件類型去找相應的驅動程序。
應用程序和VFS之間的接口是系統調用,而VFS與文件系統以及設備文件之間的接口是file_iperations結構體成員函數。
在這裏插入圖片描述

struct file_operations結構體

Linux通過註冊+回調的方式將驅動程序和系統調用聯繫起來。file_operations 中包含對文件進行打開,關閉,讀寫,控制等一些成員函數。
具體的成員函數參考:Linux 字符設備驅動結構(四)—— file_operations 結構體知識解析

static struct file_operations led_drv_fops = {
    .owner = THIS_MODULE,
    .open = led_drv_open,
    .write = led_drv_write,
};

驅動加載函數

/* 使用insmod命令安裝驅動時會調用此函數 */
int led_drv_init(void){
    int minor = 0;

    GPIOB = (GPIO *)ioremap(GPIOB_BASE, sizeof(GPIO));      // 地址映射

    major = register_chrdev(0, "led_drv", &led_drv_fops);   // 註冊驅動, 0表示動態分配主設備號
    leddrv_class = class_create(THIS_MODULE, "led_drv");
    // leddrv_class_dev = class_device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "led");     // 從3.0開始改爲device_create()
    leddrv_dev[minor] = device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "leds");

    for(minor = 1; minor < 3; minor++){
        leddrv_dev[minor] = device_create(leddrv_class, NULL, MKDEV(major, minor), NULL, "led%d", minor);
    }

    led_init();
    printk("led_drv_init\n");
end:
    return 0;
}

module_init(led_drv_init);
  • ioremap將物理地址映射到內核虛擬地址。
  • register_chrdev註冊字符設備。
  • class_create用於動態創建設備的邏輯類。---- linux驅動的類class及其節點
  • device_create用於動態的創建邏輯設備。會在/dev目錄下創建與邏輯類對應的設備文件。例如上面的程序創建了/dev/leds/dev/led1/dev/led2。主設備號相同,次設備號分別爲012
  • 最後通過宏module_init的修飾,將加載函數鏈接到.initcall段,方便內核尋找。

驅動卸載函數

void led_drv_exit(void){
    int minor;

    unregister_chrdev(major, "led_drv");   // 卸載驅動

    for(minor = 0; minor < 3; minor++){
        device_unregister(leddrv_dev[minor]);   // 與device_create()對應
    }

    class_destroy(leddrv_class);    // 與class_create()對應
    iounmap(GPIOB);
}

module_exit(led_drv_exit);
  • unregister_chrdev刪除字符設備。
  • device_unregister會刪除/sys/devices/virtual下對應的設備目錄,以及/dev下對應的設備文件。
  • class_destroy刪除設備的邏輯類。
  • module_exit修飾。

幾個內核結構體

  • struct file代表一個已經打開的文件,系統中的每個打開的文件在內核空間都有一個關聯的 struct file。
  • struct inode內核使用inode結構體在內核內部表示一個文件。

更多:Linux 字符設備驅動結構(三)—— file、inode結構體及chardevs數組等相關知識解析

Makefile

KERN_DIR = ~/linux-3.4.y

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= first_drv.o
  • KERN_DIR是內核目錄,編譯模塊前要先編譯內核。
  • make -C $(KERN_DIR) M=pwdmodules ->解釋
  • obj-m表示生成獨立的.ko文件,obj-y表示該模塊編譯到zImage

工程文件

01_LED: first_drv.c

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章