1.創建設備節點
驅動編譯成驅動模塊ko 運行驅動編譯成模塊insmod
前面成功的申請了設備號並且註冊了相應的字符設備
系統通過設備號對設備進行查找,而字符設備註冊到內核並不能直接進行設備文件操作命令(打開、關閉、讀、寫等)
需要相應的設備文件作為橋樑以此來進行設備的訪問——設備節點
設備節點被創建在/dev目錄下,將內核中註冊的設備與用户層進行鏈接,應用程序才能對設備進行訪問
/sys/class/ 目錄——class_create(…)函數對class進行創建
/include/linux/device.h”文件——class_create(…)函數對class進行創建
內核源碼/include/linux/device.h”文件——class_destroy(…)函數
內核源碼/include/linux/device.h”文件——device_create(…)函數
內核源碼/include/linux/device.h”文件——device_destroy(…)函數
手動創建設備節點
mknod NAME TYPE MAJOR MINOR
要創建的節點名稱
b表示塊設備,c表示字符設備,p表示管道
要鏈接設備的主設備號
要鏈接設備的從設備號
rk3568創建一個名為device_test的字符設備節點,鏈接設備的主設備號和從設備號分別為236和0
mknod /dev/device_test c 236 0
自動創建設備節點
利用udev(mdev)機制來實現
首先使用class_create(…)函數對class進行創建,這個類存放於/sys/class/ 目錄下
之後使用device_create(…)函數創建相應的設備,在進行模塊加載時,用户空間中的udev會自動響應device_create()函數,尋找對應的類從而創建設備節點
class_create(…)函數
用於動態創建設備的邏輯類,並完成部分字段的初始化,然後將其添加進Linux內核系統
#define class_create(owner, name) \ ({ \ static struct lock_class_key __key; \ __class_create(owner, name, &__key); \ })
struct module結構體類型的指針,指向函數即將創建的這個structclass的模塊。一般賦值為THIS_MODULE
char類型的指針,代表即將創建的struct class變量的名字
返回值:struct class * 類型的結構體。
device_create(…)函數
用來在class類中下創建一個設備屬性文件,udev會自動識別從而進行設備節點的創建
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
指定所要創建的設備所從屬的類
指定該設備的父設備,如果沒有就指定為NULL
指定創建設備的設備號
被添加到該設備回調的數據,沒有則指定為NULL
添加到系統的設備節點名稱
返回值:struct device * 類型結構體
class_destroy(…)函數
用於刪除設備的邏輯類,即從Linux內核系統中刪除設備的邏輯類
extern void class_destroy(struct class *cls);
struct module結構體類型的指針,指向函數即將創建的這個struct class的模塊。一般賦值為THIS_MODULE
char類型的指針,代表即將創建的struct class變量的名字
device_destroy(…)函數
用來刪除class類中的設備屬性文件,udev會自動識別從而進行設備節點的刪除
extern void device_destroy(struct class *cls, dev_t devt);
指定所要創建的設備所從屬的類
指定創建設備的設備號
static struct class *class_test; //表示要創建的類 static struct device *device_test; //表示要創建的設備class_test = class_create(THIS_MODULE, "class_test"); //創建類,名字為class_test device_test = device_create(class_test, NULL, dev_num, NULL, "device_test"); //創建設備,名字為device_testdevice_destroy(class_test, dev_num); //刪除設備 class_destroy(class_test); //刪除類
2.實驗:06_node創建設備節點實驗
自動申請設備號的方式進行設備號的申請
自動對設備節點進行創建
chrdev_node.c Makefile
chrdev_node.c
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/kdev_t.h> #include <linux/cdev.h> static dev_t dev_num; //定義32位的變量dev_num,用於存放設備號 static struct cdev cdev_test; //定義cdev結構體類型的變量cdev_test static struct file_operations cdev_fops_test = { //file_operations結構體 .owner = THIS_MODULE, //指向本模塊 }; static struct class *class_test; //表示要創建的類 static struct device *device_test; //表示要創建的設備 static int __init chrdev_fops_init(void) { int ret; //判斷函數返回值 int major; //定義主設備號變量 int minor; //定義次設備號變量 //動態申請設備號 ret = alloc_chrdev_region(&dev_num, 0, 1, "chrdev_name"); if(ret < 0) //申請失敗 { printk("alloc_chrdev_region is error\n"); } printk("alloc_chrdev_region is ok\n"); major = MAJOR(dev_num); //獲取主設備號 minor = MINOR(dev_num); //獲取次設備號 printk("major = %d\n", major); //打印設備號 printk("minor = %d\n", minor); //使用cdev_init()初始化cdev_test結構體,並且連接到cdev_fops_test結構體 cdev_init(&cdev_test, &cdev_fops_test); cdev_test.owner = THIS_MODULE; //將owner字段指向本模塊,防止模塊被卸載 ret = cdev_add(&cdev_test, dev_num, 1); //註冊字符設備到內核 if (ret < 0) //註冊失敗 { printk("cdev_add is error\n"); } printk("cdev_add is ok\n"); class_test = class_create(THIS_MODULE, "class_test"); //創建類,名字為class_test device_test = device_create(class_test, NULL, dev_num, NULL, "device_test"); //創建設備,名字為device_test return 0; } static void __exit chrdev_fops_exit(void) { device_destroy(class_test, dev_num); //刪除設備 class_destroy(class_test); //刪除類 cdev_del(&cdev_test); //註銷字符設備 先刪除設備,再刪除設備號 unregister_chrdev_region(dev_num, 1); //釋放設備號 printk("module exit. \n"); } module_init(chrdev_fops_init); module_exit(chrdev_fops_exit); MODULE_LICENSE("GPL v2"); //聲明模塊許可證 MODULE_AUTHOR("AFANFAN"); //聲明模塊作者
Makefile
export ARCH=arm64#設置平台架構 export CROSS_COMPILE=/opt/atk-dlrk3568-5_10_sdk-toolchain/bin/aarch64-buildroot-linux-gnu-#交叉編譯器前綴 obj-m += chrdev_node.o #此處要和你的驅動源文件同名 KDIR :=/home/alientek/rk3568_linux5.10_sdk/kernel #這裏是你的內核目錄 PWD ?= $(shell pwd) all: make -C $(KDIR) M=$(PWD) modules #make操作 clean: make -C $(KDIR) M=$(PWD) clean #make clean操作
驅動編譯成驅動模塊ko
使用命令“make”進行驅動的編譯,編譯完生成 chrdev_node.ko目標文件
運行驅動編譯成模塊insmod
開發板啓動之後, insmod chrdev_node.ko
註冊設備號的查看 cat /proc/devices
對class目錄進行查看 ls /sys/class/ 會發現class_test類被創建
對class_test 目錄 ls /sys/class/class_test/ 會發現device_test的設備節點被創建
對驅動進行卸載 rmmod chrdev_node.ko
3.問題:
好像沒有哦