当前位置: 首页 > news >正文

正点原子RK3568学习日志13-创建设备节点

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_testdevice_test = device_create(class_test, NULL, dev_num, NULL, "device_test"); //创建设备,名字为device_test
    device_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_testdevice_test = device_create(class_test, NULL, dev_num, NULL, "device_test"); //创建设备,名字为device_testreturn 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.问题:

好像没有哦

http://www.dtcms.com/a/508769.html

相关文章:

  • 网站建设销售人员培训教程wordpress注册充值
  • 惠州市 网站开发公司百度上广告怎么搞上去的
  • 【SPIE/EI/Scopus检索】2026 年第三届计算,机器学习与数据科学国际会议 (CMLDS 2026)
  • 网站建设属于淘宝哪种类目沪浙网站
  • vue 之 import 的语法
  • 网站建设采购项目部门网站建设整改
  • 做网站设计电脑买什么高端本好青岛网站建设eoeeoe
  • 网站页面制作西安广告公司联系方式
  • VS2022+DirectX9坐标系与基本图元之基本图元(BasePrimitive)_0302
  • 网站建设实训总结及体会网站开发与电子商务
  • 为什么MainWindow.xaml绑定的datacontext,EtherCATSuiteCtrl.xaml直接用了?
  • 建设企业网站综合考虑网页打不开用什么浏览器
  • 网站建设需要掌握什么知识网络营销工具的使用
  • 贪心算法深度解析:从理论到实战的完整指南
  • 基于Langchain的实践(电商客服)
  • 百度首页排名优化公司沈阳网站搜索引擎优化
  • 旅游网站建设初衷新网站应该怎么做
  • 网站做短信验证需要多少钱衡水学校网站建设
  • (立控信息LKONE)智能仓储管理,高效・安全・精准,一 “智” 到位
  • 内存管理C++
  • 建网站算法企业网站设计规范
  • 建设部网站官网 施工许可wordpress可以装多少会员数据库
  • DeepCFD+:一种工业级 CFD 代理模型训练框架【深度学习+流体力学】
  • 设计师服务平台鱼巴士医疗网站优化公司
  • 网站页面设计需要遵循的六大原则wordpress 图片链接
  • 网站网页设计培训机构浙江住房和城乡建设厅网站
  • ElectrumX介绍
  • miniAPP图片上传等api触发项目onhide等周期函数问题
  • 广州专业网站网络营销学院
  • 网站友链怎么做大鹏新网站建设