日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux驱动开发(一):字符设备

發布時間:2023/12/20 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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用于動態的創建邏輯設備。會在/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.錯誤。->參考文章
.....obj-m += key_drv.okey_drv-objs := key_drv_main.o key/key.o

工程文件

01_LED: first_drv
02_KEY: key_polling

總結

以上是生活随笔為你收集整理的Linux驱动开发(一):字符设备的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。