【Linux驱动】字符设备驱动相关宏 / 函数介绍(module_init、register_chrdev)
驱动运行有两种方式:
- 方式一:直接编译到内核,Linux内核启动时自动运行驱动程序
- 方式二:编译成模块,使用 insmod 命令加载驱动模块
我们在调试的时候,采用第二种方式是最合适的,每次修改驱动只需要编译一下驱动代码,然后使用 insmod 命令加载驱动模块( .ko 文件 ),不需要编译整个 Linux 代码。
下面以第二种方式为例,来了解一下编写字符驱动模块需要用到哪些宏或者函数。
目录
一、驱动模块的加载 / 卸载 —— module_init / module_exit
二、字符设备的注册 / 注销 —— register_chrdev
三、添加实现设备的具体操作函数
四、添加 LICENSE 和作者信息 —— MODULE_LICENSE
五、动态分配 / 释放设备号 —— alloc_chrdev_region
六、总结:字符驱动模板
一、驱动模块的加载 / 卸载 —— module_init / module_exit
驱动模块被加载,可能需要有一些初始化,但是我们要如何让内核去调用我们写的初始化函数呢,这就需要内核提供的宏: module_init 、module_exit
module_init(xxx_init); //注册模块加载函数
module_exit(xxx_exit); //注册模块卸载函数
module_init
当前模块被加载到内核时,会自动调用 xxx_init 函数,这里的 module_init 就有点像是在给内核传递 xxx_init 函数的函数指针。
module_exit
同理,当我们想卸载模块时,可能会有一些收尾工作要做,比如关闭某个引脚。当前模块被卸载的时候,会自动调用 xxx_exit 函数。
// 使用 __init 修饰
static int __init chrdevbase_init(void)
{/* 驱动入口实现 */return 0;
}// 使用 __exit 修饰
static void __exit chrdevbase_exit(void)
{/* 驱动出口实现 */
}
module_init(chrdevbase_init); //注册模块加载函数
module_exit(chrdevbase_exit); //注册模块卸载函数
二、字符设备的注册 / 注销 —— register_chrdev
注册字符设备的目的是在你的驱动被加载到内核时,会在 /dev/ 目录下生成你的字符设备文件,应用程序读写这个字符设备文件时,就会自动调用驱动中的 read / write 函数。
这样就建立起了应用程序和驱动之间的基本联系。同理,注销时,/dev/ 下对应文件会被删除。register_chrdev、unregister_chrdev 是早期注册字符设备的函数,函数声明如下:
// 字符设备注册
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops);
// 字符设备注销
static inline void unregister_chrdev(unsigned int major, const char *name);
register_chrdev 参数解析
major:主设备号,Linux 下每个设备都有一个设备号,可以使用cat /proc/devices 查看已经使用的设备号。静态分配时注意不要和已有设备号重复;如果要动态分配,可以参考第六部分《动态分配设备号》
name:设备名称,当驱动注册成功以后,在 /dev/ 下显示的名称
fops:当前驱动的操作函数集合,函数声明放在file_operations结构体中,这里要传入的就是file_operations结构体指针。
unregister_chrdev 参数解析
major:要注销的设备对应的主设备号。
name:要注销的设备对应的设备名。
三、添加实现设备的具体操作函数
上面注册字符设备的第三个参数是 fops ,这里要传入的就是你要为当前设备注册哪些操作函数,比如定义了下面的结构体,结构体对象为 chrdevbase_fops,同时要为该结构体注册 open、read、write 、close 函数:
- open 函数:chrdevbase_open
- read 函数:chrdevbase_read
- write 函数:chrdevbase_write
- close 函数:chrdevbase_release
/** 设备操作函数结构体*/
static struct file_operations chrdevbase_fops = {.owner = THIS_MODULE, // 注册当前结构体的指针对象.open = chrdevbase_open,.read = chrdevbase_read,.write = chrdevbase_write,.release = chrdevbase_release,
};
既然这里已经注册了 open、read、write 、close 函数,那么你需要自己去实现这些操作函数,关于这些函数的声明,可以在 include/linux/fs.h 的第 1588 行找到。
/* 打开设备 */
static int chrdevbase_open(struct inode *, struct file *)
{/* 用户实现具体功能 */return 0;
}/* 读取设备 */
static ssize_t chrdevbase_read(struct file *, char __user *, size_t, loff_t *);
{/* 用户实现具体功能 */return 0;
}/* 向设备写数据 */
static ssize_t chrdevbase_write(struct file *, const char __user *, size_t, loff_t *)
{/* 用户实现具体功能 */return 0;
}/* 关闭设备 */
static int chrdevbase_release (struct inode *, struct file *)
{/* 用户实现具体功能 */return 0;
}
四、添加 LICENSE 和作者信息 —— MODULE_LICENSE
驱动模块中必须添加 LICENSE 信息,不然编译会报错,作者信息可有可无。LICENSE 和作者信息的添加使用 如下两个函数:
MODULE_LICENSE("GPL"); //添加模块 LICENSE 信息
MODULE_AUTHOR("作者名"); //添加模块作者信息
五、动态分配 / 释放设备号 —— alloc_chrdev_region
动态分配设备号 —— alloc_chrdev_region
函数声明如下:
int alloc_chrdev_region(dev_t *dev, \unsigned baseminor, \unsigned count, \const char *name);
dev:输出型参数。保存申请到的设备号
baseminor:次设备号起始地址。alloc_chrdev_region 可以申请一段连续的多个设备号,这 些设备号的主设备号一样,但是次设备号不同,次设备号以 baseminor 为起始地址地址开始递 增。一般 baseminor 为 0,也就是说次设备号从 0 开始。
count:要申请的设备号数量
name:设备名字
动态释放设备号 —— unregister_chrdev_region
注销字符设备之后要释放掉设备号。函数声明如下:
void unregister_chrdev_region(dev_t from, unsigned count);
from:要释放的设备号。(这里指的是主设备号,并非上面次设备号的起始地址)
count:表示从 from 开始,要释放的设备号数量。
六、总结:字符驱动模板
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>#define CHRDEVBASE_MAJOR 200 /* 主设备号 */
#define CHRDEVBASE_NAME "chrdevbase" /* 设备名 *//* 打开设备 */
static int chrdevbase_open(struct inode *, struct file *)
{/* 用户实现具体功能 */return 0;
}/* 读取设备 */
static ssize_t chrdevbase_read(struct file *, char __user *, size_t, loff_t *);
{/* 用户实现具体功能 */return 0;
}/* 向设备写数据 */
static ssize_t chrdevbase_write(struct file *, const char __user *, size_t, loff_t *)
{/* 用户实现具体功能 */return 0;
}/* 关闭设备 */
static int chrdevbase_release (struct inode *, struct file *)
{/* 用户实现具体功能 */return 0;
}/** 设备操作函数结构体*/
static struct file_operations chrdevbase_fops = {.owner = THIS_MODULE, .open = chrdevbase_open,.read = chrdevbase_read,.write = chrdevbase_write,.release = chrdevbase_release,
};/** @description : 驱动入口函数 * @param : 无* @return : 0 成功;其他 失败*/
static int __init chrdevbase_init(void)
{int retvalue = 0;/* 注册字符设备驱动 */retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);if(retvalue < 0){printk("chrdevbase driver register failed\r\n");}printk("chrdevbase init!\r\n");return 0;
}/** @description : 驱动出口函数* @param : 无* @return : 无*/
static void __exit chrdevbase_exit(void)
{/* 注销字符设备驱动 */unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);printk("chrdevbase exit!\r\n");
}/* * 将上面两个函数指定为驱动的入口和出口函数 */
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);/* * LICENSE和作者信息*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("author_name");
相关文章:
【Linux驱动】字符设备驱动相关宏 / 函数介绍(module_init、register_chrdev)
驱动运行有两种方式: 方式一:直接编译到内核,Linux内核启动时自动运行驱动程序方式二:编译成模块,使用 insmod 命令加载驱动模块 我们在调试的时候,采用第二种方式是最合适的,每次修改驱动只需…...
axios解决跨域问题
Vue3中使用axios访问聚合的天气API,出现跨域问题,需要在前端进行一些配置: 首先是修改vue.config.js: const { defineConfig } require(vue/cli-service) module.exports defineConfig({transpileDependencies: true,devServe…...
R语言作图——热图聚类及其聚类结果输出
代码 不多说了,做个记录,代码如下。 library(pheatmap) library(RColorBrewer) # args commandArgs(TRUE) betafile "twist_common_panel_434.csv" infofile "twist_common_panel_434.txt" title "twist_common_panel&qu…...
Tomcat优化
Tomcat优化 Tomcat默认安装下的缺省配置并不适合生产环境,它可能会频繁出现假死现象需要重启,只有通过不断压测优化才能让它最高效率稳定的运行。优化主要包括三方面,分别为操作系统优化(内核参数优化),Tom…...
我的GIT练习TWO
目录 前言 GIT安装教程 Git作者 GIT优点 GIT缺点 为什么要使用 Git GIT练习TWO C1 C2 C3 C4 C5 C6 C7 总结 前言 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照,以此来对整个项目进行版本管理 GIT安装教程 点击进入查看教程…...
个人器件库整理
样品本 包含如下: 电容器件: 元件值封装备注钽电容47uF 10V1206钽电容10uF 10V1206电容10uF 10% 10V0603X5R,CL10A106KP8NNNC 元件值封装备注100nF电容50V,10%0603 电阻器件: 元件值封装备注75 Ω \Omega Ω…...
javascript——内存管理
JavaScript内存管理是Web开发中的一个重要主题。正确管理内存可以提高应用程序的性能和稳定性。本文将介绍JavaScript中的内存管理概念、常见的内存泄漏问题以及一些有效的内存管理技巧。 什么是JavaScript内存管理? JavaScript具有自动内存管理机制,开…...
Qt5.15.2安卓Android项目开发环境配置
1、Qt Creator 4.11.2 官方下载:https://download.qt.io/archive/qtcreator/4.11/4.11.2/ 镜像下载:https://mirrors.cloud.tencent.com/qt/archive/qtcreator/4.11/4.11.2/ 2、Qt 5.15.2 Android 官方更新器内部下载 参考:https://blog…...
第四十三章 弹跳训练2(灵识扫描)
“再不脱离便会陷死在里面。”这个声音似乎来自脑海深处某个隐秘角落。 双眼一睁,灵识退去,空空的头壳兀自嗡嗡作响,一股说不清道不明的失落感笼罩全身,似要将自己拖入抑郁的谷底。 不!没什么好失落沮丧的!…...
【location对象的方法,history对象,navigator--BOM】
location对象的方法 location.assign()//跟href一样,可以跳转页面(也称重定向页面) location.replace()//替换当前页面,因为不记录历史,所以不能后退页面 location.reload()//重新加载页面,相当于刷新按钮或…...
论文笔记:Normalizing Flows for Probabilistic Modeling and Inference
Abstract 正则流(Normalizing flows)提供了一种通用的机制来定义富有表达力的概率分布,只需要指定一个(通常简单的)基础分布和一系列可逆变换。 Intraduction 正则流通过将简单的密度通过一系列变换来产生更丰富、可…...
java 异常类介绍
Java 异常(Exception)是指在程序运行期间出现的错误或异常情况。Java 异常处理机制允许程序在出现异常情况时进行处理,避免程序崩溃或出现不可预知的错误 一、Java 异常的概念 Java 异常是指程序在运行期间出现的错误或异常情况。Java 异常…...
shiro 550 反序列化rce
Apach shiro 是一款开源安全框架,提供身份验证,授权,会话管理等。 shiro 550 反序列化漏洞rce 通关利用它反序列化的漏洞直接执行rce 加密的用户信息序列化后储存在名为remenber -me的cooike中。攻击者可以使用shiro默认密钥伪造cooike&am…...
【C++】---模板初阶(超详练气篇)
个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇 希望我们一起努力、成长&…...
windows系统典型漏洞分析
内存结构 缓冲区溢出漏洞 缓冲区溢出漏洞就是在向缓冲区写入数据时,由于没有做边界检查,导致写入缓冲区的数据超过预先分配的边界,从而使溢出数据覆盖在合法数据上而引起系统异常的一种现象。 ESP、EPB ESP:扩展栈指针(…...
WPF开发txt阅读器:需求分析和文件读写
文章目录 需求分析读取文本文件保存文本文件 需求分析 尽管现在比较主流的阅读格式已经是epub, modi之类的,但txt的使用范围要远比前两者广泛,所以做一个txt阅读器还是有必要的。 但是对于书籍阅读而言,纯文本不包含目录信息,这…...
C++服务器框架开发9——日志系统LogFormatter_4/各个类的关系梳理/std::function/std::get
该专栏记录了在学习一个开发项目的过程中遇到的疑惑和问题。 其教学视频见:[C高级教程]从零开始开发服务器框架(sylar) 上一篇:C服务器框架开发8——日志系统LogFormatter_3/override/宏定义优化switchcase结构 C服务器框架开发9——日志系统LogFormatt…...
arm平台上的MNN编译与运行
0.成果物 直接获取成果物见:https://download.csdn.net/download/u012824853/87867665 以下为编译、运行过程 1.编译准备 在GitHub - alibaba/MNN: MNN is a blazing fast, lightweight deep learning framework, battle-tested by business-critical use cases …...
python 编译安装指定版本 for linux
python环境是linux中必备的,部分发行版会自带python,有时候需要安装手动安装 注意:如果需要多个版本并存,建议使用conda环境,如果自己配置多版本,需要用多个软链接 conda环境,可以参考&#x…...
在Linux系统下基于Docker搭建Redis集群
创建镜像 #部署Redis集群,该集群有3个节点; --cluster-enabled yes允许启用集群; docker create --name redis-node--01 --net host -v /data/redis-data/node1:/data redis:5.0.5 --cluster-enabled yes --cluster-config-file redis-node--01.conf --port 6379…...
牛客网刷题Day5
1.内容中可以使用哪个元素来表示 <article> 标签外的内容? A aside B cite C article D class 正确答案:A 解析:<aside> 标签定义 <article> 标签外的内容,aside 的内容应该与附近的内容相关 2. 以下的HTML代码…...
Vue.js 中的动态组件是什么?如何使用动态组件?
Vue.js 中的动态组件是什么?如何使用动态组件? Vue.js是一种流行的前端框架,它提供了一种称为“动态组件”的技术,使得我们可以动态地切换组件的内容和结构。在本文中,我们将深入探讨Vue.js中的动态组件,包…...
2023年京东618预售数据:传统滋补成预售黑马,预售额超27亿
这一期主要分享一下此次京东618预售期间的一个黑马行业——传统滋补。不管是从预售量和预售额来看,传统滋补品类的成绩都是此次大促中的佼佼者。 究其原因,近几年养生滋补也掀起了一股“国潮风”。在小红书、抖音等社交平台上,关于“健康养生…...
【Linux系统基础快速入门详解】Linux 常用文件过滤编辑命令原理详解和每个命令使用场景以及实例
Linux 文件过滤编辑命令:echo,printf,cat,tee,特殊符号: {a..z},seq序列,rename 文件过滤编辑命令:echo:将字符串输出到终端或文件中。常用于输出环境变量,或者在shell脚本中输出一些提示信息。例如:echo $PATH,输出环境变量PATH的值。printf:格式化输出字符串到终端或文…...
05WEB系统的通信原理图
WEB系统的通信原理 名称作用URL统一资源定位符, 例如:http://www.baidu.com域名在https://www.baidu.com/这个网址中www.baidu.com 是一个域名IP地址计算机在网络当中的一个身份证号, 在同一个网络当中IP地址是唯一的, 有了IP地址两台计算机直接才能建立连接通信端口号一个计算…...
降低试错成本,低代码或成企业数字化转型突破口
近年来,随着市场竞争和宏观环境的双重驱动,数字化已经成为企业提升竞争性和保持可持续发展的重要手段,大多数企业意识到数字化转型的重要性,纷纷入局。 作为数据驱动业务创新的一个新方法,但行业成功的案例并不多&…...
串口助手(串口发送接收数据, 定时, 清空, hex显示)
文章目录 前言一、串口接收数据1. 默认接收,换行,hex显示2. 清空接收区数据3. 保存接受区数据 二、串口发送数据1. 默认发送2. 定时发送 三、串口助手优化1. 设置组合框当前内容。2. 未检测到串口,弹出警告。3. 载入文件 总结 前言 这篇文章…...
bp神经网络
%% 2.读取数据(两个文件) datareadmatrix(C:\Users\Administrator\Desktop\synthetic_01.csv); file_lengthlength(data); for i1:file_length %用for循环去导入第二个csv文件 namedata(i); pathstrcat(C:\Users\Administrator\Desktop\ydata.…...
strace交叉编译后对特定文件的写流程进行监控和过滤
交叉编译 为了支持strace对pid进行解析,因系统默认支持的strace版本较低,需要使用较新的版本对strace进行交叉编译,这里使用了github上的 https://github.com/strace/strace/releases 发布的strace v5.19版本,2022-08-12发布。lo…...
初识网络之TCP网络套接字
目录 一、TCP常用网络接口 1. 监听服务器 2. 接收链接 3. 发起连接 二、实现一个简单的tcp程序 1. 日志函数 2. 服务端文件 2.1 .hpp文件 2.2 .cpp文件 3. 客户端文件 3.1 .hpp文件 3.2 .cpp文件 4. 程序测试 三、实现支持多个用户并发访问的tcp程序 1. 当前程序…...
夜间正能量不良网站/群推广
近日,百度网盘终于憋出一个大招,在最新的百度网盘 PC 版 6.9.10 中,该应用新增了下载提速功能,据官方介绍,下载提速功能是百度网盘为改善用户下载体验而推出的一项功能。 不过据众多网友实测,该下载加速仅仅…...
开发公司证明房产证明/百度seo效果怎么样
2019独角兽企业重金招聘Python工程师标准>>> mtoa 检查shader的aov 仅仅读取 mtd文件中对aov的定义 例如: [attr aov_surface]aov.type INT 0x05[attr aov_Nw]aov.type INT 0x05[attr aov_fr]aov.type …...
网站建设上海网站建设公司网站/百度免费资源网站
PV 预算:成本估算部分的总价值 AC 实际成本:在规定时间内完成的成本总额 EV 挣值 ETC 剩余工作的成本估算 ETC PV - EV ETC=剩余的工作的PVCPI&a…...
安徽建设新工程信息网站/百度公司高管排名
Flask Vue.js全栈开发的 最新完整代码 及使用方式本系列的最新代码及使用方式将持续更新到: http://www.madmalls.com/blog/post/latest-code/1. Flask Vue.js全栈开发教程系列Flask Vue.js全栈开发|第1章:创建第一个Flask RESTful APIFlask …...
商务网站建设实训总结/如何做游戏推广
外部中断,通过按键来控制LED灯...
黄岛网站建设价格/汕头百度网站推广
http://scikit-learn.org/stable/modules/decomposition.html#lsa 2.5.1:PCA 标准PCA:只支持批量处理 incremental PCA:支持分批处理,对于内存容不下的情况很好 Approximate PCA:RandomizedPCA 通过computation to …...