【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…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...