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

【Linux】【驱动】自动创建设备节点

【Linux】【驱动】自动创建设备节点

  • 驱动代码
  • 操作指令
    • linux端
    • 从机端

这里展示了如何自动的方式去创建一个字符类的节点
下面就是需要调用到的程序

函数

 void cdev_init(struct cdev *, const struct file_operations *);

第一个参数 要初始化的 cdev
第二个参数 文件操作集 cdev->ops = fops; //实际就是把文件操作集写给 ops
功能 cdev_init()函数用于初始化 cdev 的成员,并建立 cdev 和 file_operations 之间的连接。

函数

 int cdev_add(struct cdev *, dev_t, unsigned);

第一个参数 cdev 的结构体指针
第二个参数 设备号
第三个参数 次设备号的数量
功能 cdev_alloc()函数用于动态申请一个 cdev 内存

void cdev_del(struct cdev *);

cdev 的结构体指针

生成设备节点
字符设备注册完以后不会自动生成设备节点。我们需要使用 mknod 命令创建一个设备节点
格式:mknod 名称 类型 主设备号 次设备号

mknod /dev/test c 247 0

驱动代码

代码实现的流程

从 hello_init 函数开始看,

  1. 注册设备号,
  2. 初始化 cdev
  3. 向系统注册设备
  4. 创建 class 类
  5. 在 class 类下创建设备

从hello_exit 来看

  1. 注销设备号
  2. 删除设备
  3. 注销设备
  4. 删除类
#include <linux/init.h>
#include <linux/module.h>     //最基本的文件,支持动态添加和卸载模块。
#include <linux/fs.h>        //包含了文件操作相关 struct 的定义,例如大名鼎鼎的 struct file_operations
#include <linux/kdev_t.h>
#include <linux/cdev.h> //对字符设备结构 cdev 以及一系列的操作函数的定义。//包含了 cdev 结构及相关函数的定义。
#include <linux/device.h> //包含了 device、class 等结构的定义#define DEVICE_NUMBER 1 		//定义次设备号的个数
#define DEVICE_SNAME "schrdev"  //定义静态注册设备的名称
#define DEVICE_ANAME "achrdev"  //定义动态注册设备的名称
#define DEVICE_MINOR_NUMBER 0 	//定义次设备号的起始地址#define DEVICE_CLASS_NAME "chrdev_class" //宏定义类名
#define DEVICE_NODE_NAME "chrdev_test" //宏定义设备节点的名字static int major_num, minor_num; //定义主设备号和次设备号struct class *class; //定义类
struct device *device; /* 设备 */
struct cdev cdev;//定义一个 cdev 结构体module_param(major_num,int,S_IRUSR); //驱动模块传入普通参数 major_num
module_param(minor_num ,int,S_IRUSR);//驱动模块传入普通参数 minor_numdev_t dev_num;/**
* @description: 打开设备
* @param {structinode} *inode:传递给驱动的 inode
* @param {structfile} *file:设备文件,file 结构体有个叫做 private_data 的成员变量,
* 一般在 open 的时候将 private_data 指向设备结构体。
* @return: 0 成功;其他 失败
*/
int chrdev_open(struct inode *inode, struct file *file)
{printk("chrdev_open\n");return 0;
}// 设备操作函数结构体
struct file_operations chrdev_ops = {.owner = THIS_MODULE,.open = chrdev_open};/**
* @description: 驱动入口函数
* @param {*}无
* @return {*} 0 成功;其他 失败
*/
static int hello_init(void)
{int ret;//函数返回值if(major_num){/*静态注册设备号*/printk("major_num = %d\n",major_num);//打印传入进来的主设备号printk("minor_num = %d\n",minor_num);//打印传入进来的次设备号dev_num = MKDEV(major_num,minor_num);//MKDEV 将主设备号和次设备号合并为一个设备号ret = register_chrdev_region(dev_num, DEVICE_NUMBER,DEVICE_SNAME);//注册设备号if(ret<0){printk("register_chrdev_region error\n");}//静态注册设备号成功,则打印。printk("register_chrdev_region ok\n");}else{/*动态注册设备号*/ret = alloc_chrdev_region(&dev_num,DEVICE_MINOR_NUMBER,1, DEVICE_ANAME);if(ret<0){printk("alloc_chrdev_region error\n");}//动态注册设备号成功,则打印printk("alloc_chrdev_region ok\n");major_num =MAJOR(dev_num); //将主设备号取出来minor_num = MINOR(dev_num);//将次设备号取出来printk("major_num = %d\n",major_num);//打印传入进来的主设备号printk("minor_num = %d\n",minor_num);//打印传入进来的次设备号}// 初始化 cdevcdev.owner = THIS_MODULE;//cdev_init 函数初始化 cdev 结构体成员变量cdev_init(&cdev, &chrdev_ops);//完成字符设备注册到内核cdev_add(&cdev, dev_num, DEVICE_NUMBER);//创建类class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);// 在 class 类下创建设备device = device_create(class, NULL, dev_num, NULL, DEVICE_NODE_NAME);return 0;
}//drivers for exit 
static void hello_exit(void)
{//注销设备号unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);//删除设备cdev_del(&cdev);//注销设备device_destroy(class, dev_num);//删除类class_destroy(class);printk("gooodbye! \n");}module_init(hello_init);
module_exit(hello_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris");

下面就是app的代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char *argv[])
{int fd;char buf[64] = {0};fd = open("/dev/chrdev_test",O_RDWR); //打开设备节点if(fd < 0){perror("open error \n");return fd;}//read(fd,buf,sizeof(buf)); //从文件中读取数据放入缓冲区中close(fd);return 0;
}

操作指令

linux端

arm-buildroot-linux-gnueabihf-gcc -o app app.c
cp app /home/book/nfs_rootfs/

从机端

驱动卸载掉,再加载新编译好的的驱动

rmmod chrdev
insmod chrdev.ko

我们输入以下命令查看/sys/class 下面是否生成类,

ls /sys/class/chrdev_class/

查看下是否生成了设备节点

ls /sys/class/

来验证生成的设备节点是否可以使用

 ./app

在这里插入图片描述

相关文章:

【Linux】【驱动】自动创建设备节点

【Linux】【驱动】自动创建设备节点 续驱动代码操作指令linux端从机端 续 这里展示了如何自动的方式去创建一个字符类的节点 下面就是需要调用到的程序 函数 void cdev_init(struct cdev *, const struct file_operations *);第一个参数 要初始化的 cdev 第二个参数 文件操作…...

自实现getprocaddress(名称查找或者序号查找)

通过名称去找 // MyGETPRCOADDRESS.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> #include<Windows.h>/*WINBASEAPI //导出不需要使用&#xff0c;那么我们注释掉*/ FARPROC WINAPI MyGetProcAddress(_In_ HMO…...

如何DIY制作干洗店洗护小程序

洗护行业正逐渐迎来线上化的浪潮&#xff0c;传统的干洗店也开始尝试将业务线上化&#xff0c;以提供更便捷的服务给消费者。而制作一款洗护小程序&#xff0c;成为了干洗店实现线上化的重要一环。今天&#xff0c;我们就来分享一下如何使用第三方制作平台制作洗护小程序的教程…...

微前沿 | 第1期:强可控视频生成;定制化样本检索器;用脑电重建视觉感知;大模型鲁棒性评测

欢迎阅读我们的新栏目——“微前沿”&#xff01; “微前沿”汇聚了微软亚洲研究院最新的创新成果与科研动态。在这里&#xff0c;你可以快速浏览研究院的亮点资讯&#xff0c;保持对前沿领域的敏锐嗅觉&#xff0c;同时也能找到先进实用的开源工具。 本期内容速览 01. 强可…...

SQLite数据库C_C++接口(保姆级API应用 1.4W字)(全网最详细介绍,学完必掌握)

目录 sqlite3的C/C API应用 前言 SQLite3库安装 API函数 打开、关闭、错误处理 打开 返回值 关闭 错误调试 实际应用 执行SQL&#xff08;DDL、DML&#xff09; API介绍 实际应用 回调函数查询 API介绍 实际应用 全缓冲查询 API介绍 实际应用 字节缓冲查询…...

倒计时:心理的镇静剂还是焦虑的火种?

倒计时&#xff1a;心理的镇静剂还是焦虑的火种&#xff1f; 目录 引言倒计时的作用与原理倒计时的双面性&#xff1a;缓解焦虑还是引发焦虑&#xff1f;如何正确使用倒计时结论 引言 在我们的日常生活和工作中&#xff0c;倒计时被广泛的应用。无论是在网购的抢购活动中&a…...

迅睿系统二开自定义函数和插件的自定义函数

全局的自定义函数&#xff1a; 全局的自定义函数文件&#xff1a;dayrui/My/Helper.php 此文件用于放网站自定义函数&#xff0c;程序会自动加载 当前站点的自定义函数文件&#xff1a;网站主目录/config/custom.php 插件的自定义函数&#xff1a; 基于App目录下的插件或模块…...

传统品牌如何通过3D虚拟数字人定制和动捕设备加速年轻化发展?

步入Z时代&#xff0c;年轻一代消费者的生活方式深受互联网技术和媒介环境影响&#xff0c;对新潮事物感兴趣&#xff0c;消费思维也相对前卫&#xff0c;品牌需要探索契合Z世代的消费观念&#xff0c;寻找新的链接拉近品牌与消费者的距离&#xff0c;而3D虚拟数字人定制可以帮…...

sql:SQL优化知识点记录(五)

&#xff08;1&#xff09;explain之例子 &#xff08;2&#xff09;索引单表优化案例 上面的功能已经实现&#xff0c;但是分析功能&#xff0c; 使用explain分析这条sql&#xff1a; 发现type为All Extra&#xff1a;有Using filesort &#xff08;文件内排序&#xff09; 这…...

1.3 Metasploit 生成SSL加密载荷

在本节中&#xff0c;我们将介绍如何通过使用Metasploit生成加密载荷&#xff0c;以隐藏网络特征。前一章节我们已经通过Metasploit生成了一段明文的ShellCode&#xff0c;但明文的网络传输存在安全隐患&#xff0c;因此本节将介绍如何通过生成SSL证书来加密ShellCode&#xff…...

redis windows 版本安装

1. 下载windows安装包并解压 如果是Linux版本可以直接到官网下载&#xff0c;自3.x起官网和微软网站就没有redis安装包更新了&#xff0c;好在github有开发者在编译发布更新&#xff08;目前最新有5.0.9版本可下&#xff09;&#xff0c;地址&#xff1a;redis windows 5版本下…...

限流算法深入

限流定义及目的 当系统流量达到系统或下游承受能力的阈值时对系统进行限流控制以防止系统或下游挂掉&#xff0c;减少影响面。 限流组成&#xff1a;阈值及限流策略。阈值是指系统单位时间接收到的请求qps总数&#xff1b;限流策略是指限流行业触发后对应的系统行为&#xff…...

java 基础知识 循环的几个题目

1、输出1~100的累加和 结果显示在屏幕&#xff0c;显示在文件res1.txt中 2、输出1-~100的偶数和 结果显示在屏幕&#xff0c;显示在文件res2.txt中 3、输出所有水仙花数&#xff1a; 100~999的数中出现个位数的立方十位数的立方百位数的立方这个数本身 4、输出由9行9列星号组成…...

Spring Boot使用LocalDateTime、LocalDate作为入参

0x0 背景 项目中使用LocalDateTime系列作为dto中时间的类型&#xff0c;但是spring收到参数后总报错&#xff0c;为了全局配置时间类型转换&#xff0c;尝试了如下3中方法。 注&#xff1a;本文基于Springboot2.0测试&#xff0c;如果无法生效可能是spring版本较低导致的。PS&…...

第七周第七天学习总结 | MySQL入门及练习学习第二天

实操练习&#xff1a; 1.创建一个名为 cesh的数据库 2.在这个数据库内 创建一个名为 xinxi 的表要求该表可以包含&#xff1a;编号&#xff0c;姓名&#xff0c;备注的信息 3.为 ceshi 表 添加数据 4.为xinxi 表的数据设置中文别名 5.查询 在 xinxi 表中编号 为2 的全部…...

【考研数学】线形代数第三章——向量 | 3)向量组秩的性质、向量空间、过渡矩阵

文章目录 引言三、向量组等价、向量组的极大线性无关组与秩3.2 向量组秩的性质 四、 n n n 维向量空间4.1 基本概念4.2 基本性质 写在最后 引言 紧接前文学习完向量组秩的基本概念后&#xff0c;继续往后学习向量的内容。 三、向量组等价、向量组的极大线性无关组与秩 3.2 向…...

【技术】SpringBoot Word 模板替换

SpringBoot Word 模板替换 什么是 Word 模板替换如何实现 Word 模板替换 什么是 Word 模板替换 模板一般是具有固定格式的内容&#xff0c;其中一部分需要替换。Word 模板通俗的讲是以 Word 的形式制作模板&#xff0c;固定格式和内容&#xff0c;然后将其中的一部分数据替换掉…...

java jni nv21和nv12互转

目录 libyuv性能比较 NV12 NV21 YUV420格式介绍 jni YUV420toYUV420SemiPlanar java YUV420toYUV420SemiPlanar java NV12toYUV420SemiPlanar jni NV12toYUV420SemiPlanar...

后端面试话术集锦第二篇:spring boot面试话术

🚗后端面试集锦目录 💖后端面试话术集锦第一篇:spring面试话术💖 💖后端面试话术集锦第二篇:spring boot面试话术💖 💖后端面试话术集锦第三篇:spring cloud面试话术💖 💖后端面试话术集锦第四篇:ElasticSearch面试话术💖 💖后端面试话术集锦第五篇:r…...

Doris中分区和分桶使用教程

1 分区与分桶 Doris中有两层的数据划分&#xff0c;第一层是分区&#xff08;Partition&#xff09;&#xff0c;第二层是分桶&#xff08;Bucket&#xff09;&#xff0c; Partition又能分为Range分区和List分区。 Bucket仅支持Hash方式。 1.1 Partition 只能指定…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...