字符设备驱动开发-注册-设备文件创建
一、字符设备驱动
linux系统中一切皆文件
1、应用层: APP1 APP2 ...
fd = open("led驱动的文件",O_RDWR);
read(fd);
write();
close();
2、内核层:
对灯写一个驱动
led_driver.c
driver_open();
driver_read();
driver_write();
driver_close();
struct file_operations
{
int (*open) (struct inode *, struct file *);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*release) (struct inode *, struct file *);//(close)
}
cdev:
设备号1 设备号2 设备号n
设备驱动1 设备驱动2 .... 设备驱动n
设备号:32位,无符号数字
高12位 :主设备号 :区分哪一类设备
低20位 :次设备号 :区分同类中哪一个设备
3、硬件层: LED uart ADC PWM
每个驱动里面都有对应的file_operations
1)open的过程:
open打开文件,这个文件与底层的驱动的设备号有关系,
通过设备号访问设备驱动中的struct file_operations里面的open函数。
2)read的过程:
open函数会有一个返回值,文件描述符fd,read函数通过fd
找到驱动中的struct file_operations里面的read函数。
Led驱动:字符设备 步骤:
- 注册字符设备驱动 - 得到一个字符设备驱动的框架,并且得到设备号
- 确定操作的硬件设备 - led灯(初始化灯)
- 初始化灯(先建立灯实际物理地址和虚拟地址之间的映射)-
- 基于操作系统开发,操作虚拟内存,
- 用户空间数据拷贝到内核空间数据的交互(用户使用的时候,驱动才会被真正运行,涉及数据交互)
- 在应用层创建一个设备文件(设备节点)
file_operations 操作方法结构体
struct file_operations
{
int (*open) (struct inode *, struct file *);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*release) (struct inode *, struct file *);//(close)
}
二、字符设备驱动的注册
1、注册一个字符设备驱动register_chrdev
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
功能:注册一个字符设备驱动
参数:@major:主设备号
:如果你填写的值大于0,它认为这个就是主设备号
:如果你填写的值为0,操作系统给你分配一个主设备号@name :名字 cat /proc/devices @fops :操作方法结构体
返回值:major>0 ,成功返回0,失败返回错误码(负数) vi -t EIO
major=0,成功主设备号,失败返回错误码(负数) 当注册一个字符设备驱动的时候。 如果成功的话,当你使用cat /proc/devices 命令查看的时候可以看到系统自动分配的主设备号和这个名字
2、注销一个字符设备驱动
void unregister_chrdev(unsigned int major, const char *name)
功能:注销一个字符设备驱动
参数:@major:主设备号@name:名字
返回值:无
三、手动创建设备文件 mknod
sudo mknod led (路径是任意) c/b 主设备号 次设备号
sudo –rf led 删除的时候记得加-rf





1、设备驱动程序
#include <linux/module.h>
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/fs.h>#define NAME "chrdev_devled"int major = 0; //保存主设备号
// open read write release 初始化
int myopen(struct inode *node, struct file *file_t)
{printk("%s %s %d\n", __FILE__, __func__, __LINE__);return 0;
}
ssize_t myread(struct file *file_t, char __user *ubuf, size_t n, loff_t *off_t)
{printk("%s %s %d\n", __FILE__, __func__, __LINE__);return 0;
}
ssize_t mywrite(struct file *file_t, const char __user *ubuf, size_t n, loff_t *off_t)
{printk("%s %s %d\n", __FILE__, __func__, __LINE__);return 0;
}
int myclose(struct inode *node, struct file *file_t)
{printk("%s %s %d\n", __FILE__, __func__, __LINE__);return 0;
}
struct file_operations fops = {.open = myopen,.read = myread,.write = mywrite,.release = myclose,
};
//入口函数
static int __init chrdev_init(void)
{printk("%s %s %d\n", __FILE__, __func__, __LINE__);//注册字符设备驱动: 主设备号 驱动名 结构体
major=register_chrdev(major, NAME, &fops);//容错判断if(major < 0){printk("chrdev_register err.\n");return -EINVAL;}return 0;
}
//出口函数
static void __exit chrdev_exit(void)
{printk(KERN_ERR "%s %s %d\n", __FILE__, __func__, __LINE__);//注销字符设备驱动unregister_chrdev(major, NAME);
}
module_init(chrdev_init);//入口
module_exit(chrdev_exit);//出口
MODULE_LICENSE("GPL");//协议
2、应用层读取程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#include <stdio.h>int main(int argc,char *argv[])
{
int fd = -1;
char buf[32] = "";if(argc < 2){
printf("请输入要打开的文件\n");return 1;} fd = open(argv[1],O_RDWR);if(fd < 0){
printf("open %s failed\n",argv[1]);return 2;}
read(fd,buf,sizeof(buf));
write(fd,buf,sizeof(buf));
read(fd,buf,sizeof(buf));
write(fd,buf,sizeof(buf));
printf("buf=%s\n",buf);
close(fd);
fd = -1;return 0;
}
3、操作步骤:
--make 驱动文件

--insmod 安装驱动
--cat /proc/devicse 查看设备号

--sudo mknod led c 244 0 创建设备文件(设备节点)

--dmesg 查看消息
--sudo dmesg -C删除消息
--sudo gcc app.c 编译应用层读取文件

--./app .led读取
--led--dmesg 查看消息

相关文章:
字符设备驱动开发-注册-设备文件创建
一、字符设备驱动 linux系统中一切皆文件 1、应用层: APP1 APP2 ... fd open("led驱动的文件",O_RDWR); read(fd); write(); close(); 2、内核层: 对灯写一个驱动 led_driver.c driver_open(); driver_read(); driver_write(…...
TrustZone之可信操作系统
有许多可信内核,包括商业和开源的。一个例子是OP-TEE,最初由ST-Ericsson开发,但现在是由Linaro托管的开源项目。OP-TEE提供了一个功能齐全的可信执行环境,您可以在OP-TEE项目网站上找到详细的描述。 OP-TEE的结构如下图所示&…...
java定义三套场景接口方案
一、背景 在前后端分离开发的背景下,后端java开发人员现在只需要编写接口接口。特别是使用微服务开发的接口。resful风格接口。那么一般后端接口被调用有下面三种场景。一、不需要用户登录的接口调用,第二、后端管理系统接口调用(需要账号密…...
idea连接数据库,idea连接MySQL,数据库驱动下载与安装
文章目录 普通Java工程先创建JAVA工程JDBC连接数据库测试连接 可视化连接数据库数据库驱动下载与安装常用的数据库驱动下载MySQL数据库Oracle数据库SQL Server 数据库PostgreSQL数据库 下载MySQL数据库驱动JDBC连接各种数据库的连接语句MySQL数据库Oracle数据库DB2数据库sybase…...
Redis-实践知识
转自极客时间Redis 亚风 原文视频:https://u.geekbang.org/lesson/535?article681062 Redis最佳实践 普通KEY Redis 的key虽然可以自定义,但是最好遵循下面几个实践的约定: 格式:[业务名称]:[数据名]:[id] 长度不超过44字节 不…...
多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测
多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测 目录 多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现…...
leetcode160相交链表思路解析
分别让tmp1以及tmp2的结点分别先指向headA以及headB,当遍历完成后,再让tmp1以及tmp2分别指向haedB和headA反转 此处有个问题:为什么if判断句中写tmp1!=nullptr,能够编译通过,但是写tmp1->ne…...
在线分析工具-日志优化
一、概述 针对于大日志文件,统计分析出日志文件的相关指标,帮助开发测试人员,优化日志打印。减少存储成本 二、日志分析指标 重复打印日志:统一请求reqId的重复打印日志打印最多的方法:检测出打印日志最多的方法…...
硬核实战!mysql 错误操作整个表全部数据后如何恢复?附解决过程、思路(百万行SQL,通过binlog日志恢复)
mysql 错误操作整个表全部数据后如何恢复?(百万行SQL,通过binlog日志恢复) 事件起因 事情起因:以为某个表里的数据都是系统配置的数据,没有用户数据,一个字段需要覆盖替换为新的url链接&#x…...
【什么是反射机制?为什么反射慢?】
✅ 什么是反射机制?为什么反射慢? ✅典型解析✅拓展知识仓✅反射常见的应用场景✅反射和Class的关系 ✅典型解析 反射机制指的是程序在运行时能够获取自身的信息。在iava中,只要给定类的名字,那么就可以通过反射机制来获得类的所有…...
PostGreSQL:货币类型
货币类型:money money类型存储固定小数精度的货币数字,小数的精度由数据库的lc_monetary设置决定。windows系统下,该配置项位于/data/postgresql.conf文件中,默认配置如下, lc_monetary Chinese (Simplified)_Chi…...
ESP8266网络相框采用TFT_eSPI库TJpg_Decoder库mixly库UDP库实现图片传送
用ESP8266和TFT_ESPI模块来显示图片数据。具体来说,我们将使用ILI9431显示器作为显示设备,并通过UDP协议将图片数据从发送端传输到ESP8266。最后,我们将解析这些数据并在TFT屏幕上显示出来。在这个过程中,我们将面临一些编程挑战&…...
Go 泛型发展史与基本介绍
Go 泛型发展史与基本介绍 Go 1.18版本增加了对泛型的支持,泛型也是自 Go 语言开源以来所做的最大改变。 文章目录 Go 泛型发展史与基本介绍一、为什么要加入泛型?二、什么是泛型三、泛型的来源四、为什么需要泛型五、Go 泛型设计的简史六、泛型语法6.1 …...
python 解决手机拍的书籍图片发灰的问题
老师给发的作业经常是手机拍的,而不是扫描,背景发灰,如果二次打印就没有看了,象这样: 如果使用photoshop 处理,有些地方还是扣不干净,不如python 做的好,处理后如下: 具体…...
【prompt一】Domain Adaptation via Prompt Learning
1.Motivation 当前的UDA方法通过对齐源和目标特征空间来学习域不变特征。这种对齐是由诸如统计差异最小化或对抗性训练等约束施加的。然而,这些约束可能导致语义特征结构的扭曲和类可辨别性的丧失。 在本文中,引入了一种新的UDA提示学习范式࿰…...
视频编辑与制作,添加视频封面的软件
如今,视频已经成为了我们生活中不可或缺的一部分,无论是社交媒体上的短视频,还是电影、电视剧,视频都以其独特的魅力吸引着我们的目光。而在这背后,视频剪辑软件功不可没。今天,我就为大家揭秘一款新一代的…...
Deepin更换仿Mac主题
上一篇博客说了要写一篇deepin系统的美化教程 先看效果图: 准备工作: 1.你自己 嘻嘻嘻 2.能上网的deepin15.11电脑 首先去下载主题 本次需要系统美化3部分:1.图标 2.光标 3.壁纸 开始之前,请先把你的窗口特效打开,…...
【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse
【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse 1)导入相关依赖2)代码实现2.1.resources2.1.1.appconfig.yml2.1.2.log4j.properties2.1.3.log4j2.xml2.1.4.flink_backup_local.yml 2.2.utils2.2.1.DBConn2.2.2.CommonUtils2.…...
浅谈Redis分布式锁(下)
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 自定义Redis分布式锁的…...
Django Rest Framework框架的安装
Django Rest Framework框架的安装 Django Rest Framework框架的安装 1.DRF简介2.安装依赖3.安装使用pip安装添加rest_framework应用 1.DRF简介 Django REST Framework是Web api的工具包。它是在Django框架基础之上,进行了二次开发。 2.安装依赖 链接python安装 …...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
