Linux驱动开发(一):字符设备
生活随笔
收集整理的這篇文章主要介紹了
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 結構體知識解析
驅動加載函數
/* 使用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用于動態的創建邏輯設備。會在/sys/devices/virtual目錄下創建新的邏輯設備目錄,在/dev目錄下創建與邏輯類對應的設備文件。例如上面的程序創建了/dev/leds,/dev/led1,/dev/led2。主設備號相同,次設備號分別為0,1,2。
- 最后通過宏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.yall:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m += first_drv.o- KERN_DIR是內核目錄,編譯模塊前要先編譯內核。
- make -C $(KERN_DIR) M=`pwd` modules ->參考文章
- obj-m表示生成獨立的.ko文件,obj-y表示該模塊編譯到zImage
- 多個源文件時:obj-m表示生成的驅動文件名,*-objs表示所有依賴,且所有源文件不能與生成的驅動名同名,否則會報module license 'unspecified' taints kernel.錯誤。->參考文章
工程文件
01_LED: first_drv
02_KEY: key_polling
總結
以上是生活随笔為你收集整理的Linux驱动开发(一):字符设备的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C/C++】字节对齐 ALIGN宏
- 下一篇: linux E667 同步失败