嵌入式驱动开发详解2(设备挂载问题)

news2024/11/28 23:35:15

文章目录

  • 前言
  • 设备号
    • 设备号的组成
    • 设备号的分配
      • 静态分配
      • 动态分配
  • 驱动挂载与卸载
  • 设备节点创建
  • 驱动挂载出现问题

前言

驱动的设备挂载和卸载是十分重要的内容,一旦操作不当可能会导致系统崩溃,接下来我将用字符设备的驱动挂载原理进行详细讲解,并把自己在学习过程中遇到的问题与解决办法进行展示。

设备号

设备号的组成

为了方便管理,Linux 中每个设备都有一个设备号,设备号由主设备号和次设备号两部分 组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备 (后面有关杂项MISC的平台开发是根据不同的次设备号实现的)。 Linux 提供了 一个名为 dev_t 的数据类型表示设备号,dev_t 定义在文件 include/linux/types.h 里面,dev_t 其实就是 unsigned int 类型,是一个 32 位的数据类型。这 32 位的数据构成了主设备号和次设备号两部分,其中高 12 位为主设备号,低 20 位为次设备号。因此 Linux 系统中主设备号范围为 0~4095,所以大家在选择主设备号的时候一定不要超过这个范围。在文 件 include/linux/kdev_t.h 中提供了几个关于设备号的操作函数(本质是宏),如下所示:

#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1) 
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) 
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) 
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))

其中:
宏 MINORBITS 表示次设备号位数,一共是 20 位。
宏 MINORMASK 表示次设备号掩码。
宏 MAJOR 用于从 dev_t 中获取主设备号,将 dev_t 右移 20 位即可。
宏 MINOR 用于从 dev_t 中获取次设备号,取 dev_t 的低 20 位的值即可。
宏 MKDEV 用于将给定的主设备号和次设备号的值组合成 dev_t 类型的设备号。

设备号的分配

静态分配

注册字符设备的时候需要给设备指定一个设备号,这个设备号可以是驱动开发者静态的指定一个 设备号,比如选择 200 这个主设备号。有一些常用的设备号已经被 Linux 内核开发者给分配掉 了,具体分配的内容可以查看文档 Documentation/devices.txt。并不是说内核开发者已经分配掉 的主设备号我们就不能用了,具体能不能用还得看我们的硬件平台运行过程中有没有使用这个 主设备号,使用 “cat /proc/devices” 命令即可查看当前系统中所有已经使用了的设备号。

动态分配

静态分配设备号需要我们检查当前系统中所有被使用了的设备号,然后挑选一个没有使用 的。而且静态分配设备号很容易带来冲突问题,Linux 社区推荐使用动态分配设备号,在注册字 符设备之前先申请一个设备号,系统会自动给你一个没有被使用的设备号,这样就避免了冲突。 卸载驱动的时候释放掉这个设备号即可。
设备号的申请函数如下:

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 

函数 alloc_chrdev_region 用于申请设备号,此函数有 4 个参数:
dev:保存申请到的设备号。
baseminor:次设备号起始地址,alloc_chrdev_region 可以申请一段连续的多个设备号,这 些设备号的主设备号一样,但是次设备号不同,次设备号以 baseminor 为起始地址地址开始递 增。一般 baseminor 为 0,也就是说次设备号从 0 开始。
count:要申请的设备号数量。
name:设备名字。
注销字符设备之后要释放掉设备号,设备号释放函数如下:

void unregister_chrdev_region(dev_t from, unsigned count) 

此函数有两个参数:
from:要释放的设备号。
count:表示从 from 开始,要释放的设备号数量。

驱动挂载与卸载

输入如下命令加载 chrdevbase.ko 驱动文件:

insmod chrdevbase.ko 
//或者
modprobe chrdevbase.ko

如果不再使用某个设备的话可以将其驱动卸载掉,比如输入如下命令卸载掉 chrdevbase 这 个设备:

rmmod chrdevbase.ko

驱动挂载或者卸载之后可以通过下面这两个指令查看

lsmod
cat /proc/devices

此时这里只是设备被挂载了,有对应的设备号,但是不一定能自动创建节点,驱动加载成功需要在/dev 目录下创建一个与之对应的设备节点文件,应用程序就是通过操作这个设备节点文件来完成对具体设备的操作。关于是否创建了节点可以看后面的内容)
一般情况下我们都会在驱动函数里面配置好设备的节点,如果没有配置好节点的话需要我们手动配置,手动配置流程如下:输入如下命令创建/dev/chrdevbase 这个设备节 点文件:

mknod /dev/chrdevbase c 200 0 

其中“mknod”是创建节点命令,“/dev/chrdevbase”是要创建的节点文件,“c”表示这是个 字 符 设 备 ,“ 200 ” 是 设 备 的 主 设 备 号 ,“ 0 ” 是 设 备 的 次 设 备 号 。 创 建 完 成 以 后 就 会 存 在 /dev/chrdevbase 这个文件,可以使用 “ls /dev/chrdevbase -l” 命令查看。

设备节点创建

字符设备驱动开发重点是使用 register_chrdev 函数注册字符设备,当不再使用设备的时候就使用 unregister_chrdev 函数注销字符设备, 当使用这两个函数时,驱动模块加载成功以后还需要手动使用 mknod 命令创建 设备节点。 register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数,现在新的字符设备驱动已经不再使用这两个函数,而是使用 Linux 内核推荐的新字符设备驱动 API 函数。关于设备节点的具体内容如下:
mdev机制:设备的节点自动创建主要是依赖于这个机制。
udev 是一个用户程序,在 Linux 下通过 udev 来实现设备文件的创建与删除,udev 可以检 测系统中硬件设备状态,可以根据系统中硬件设备状态来创建或者删除设备文件。比如使用 modprobe 命令成功加载驱动模块以后就自动在/dev 目录下创建对应的设备节点文件,使用 rmmod 命令卸载驱动模块以后就删除掉/dev 目录下的设备节点文件。 使用 busybox 构建根文件 系统的时候,busybox 会创建一个 udev 的简化版本—mdev,所以在嵌入式 Linux 中我们使用mdev 来实现设备节点文件的自动创建与删除, Linux 系统中的热插拔事件也由 mdev 管理,在 /etc/init.d/rcS 文件中如下语句:

echo /sbin/mdev > /proc/sys/kernel/hotplug 

上述命令设置热插拔事件由 mdev 来管理,关于 udev 或 mdev 更加详细的工作原理这里就 不详细探讨了,我们重点来学习一下如何通过 mdev 来实现设备文件节点的自动创建与删除。
自动创建设备节点需要经过以下过程

  • 1、手动或者自动创建一个设备号
  • 2、使用 cdev 结构体表示一个字符设备,在 cdev 中有两个重要的成员变量:ops 和 dev,这两个就是字符设备文件操作函数集合 file_operations 以及设备号 dev_t。
  • 3、在 cdev_add 函数后面添加自动创建设备节点相关代码。这一步开始才是跟自动创建设备节点相关的内容,前面两步是铺垫。
  • 4、首先要创建一个 class 类,class 是个结构体。
  • 5、在这个类下创建一个设备。使用 device_create 函数在类下面创建设备。
    通过以上步骤,设备的节点便可实现自动挂载,挂载至/dev目录下。

驱动挂载出现问题

在做一次按键扫描的驱动阻塞实验时,发现把设备名称改为blockio时,通过modprobe可以将设备挂载成功,但是不能通过一个app程序去运行这个节点,经过查找原因,发现/dev目录下的blockio文件不是字符类型的设备,而是块类型设备,具体是什么设备可以通过brw-rw----前面的b和c推断出来,随后我用手动创建节点的方式将这个节点强制变为字符设备的形式在去用app程序运行这个节点便可以成功。具体的过程可以见下图:
在这里插入图片描述
当我们名称里面不含block时,自动生成的节点都是字符类型的可以运行,可能是block这个词汇比较敏感导致的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2249373.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谈谈微服务的常用组件

由于微服务给系统开发带来了一些问题和挑战&#xff0c;如服务调用的复杂性、分布式事务的处理、服务的动态管理等&#xff0c;为了更好地解决这些问题和挑战&#xff0c;各种微服务治理的组件应运而生&#xff0c;充当微服务架构的基石和支撑&#xff0c;常用组件如下表&#…

【数字图像处理+MATLAB】通过迭代全局阈值处理算法(Iterative Global Algorithm)实现图像分割

引言 图像分割是将数字图像划分为多个区域&#xff08;或像素的集合&#xff09;的过程&#xff0c;这些区域通常对应于真实世界的物体或图像中的特定部分。图像分割的目标是简化或改变图像的表示形式&#xff0c;使得图像更容易理解和分析。图像分割通常用于定位图像中的物体…

【三维生成】Edify 3D:可扩展的高质量的3D资产生成(英伟达)

标题&#xff1a;Edify 3D: Scalable High-Quality 3D Asset Generation 项目&#xff1a;https://research.nvidia.com/labs/dir/edify-3d demo&#xff1a;https://build.nvidia.com/Shutterstock/edify-3d 文章目录 摘要一、前言二、多视图扩散模型2.1.消融研究 三、重建模型…

在SQLyog中导入和导出数据库

导入 假如我要导入一个xxx.sql&#xff0c;我就先创建一个叫做xxx的数据库。 然后右键点击导入、执行SQL脚本 选择要导入的数据库文件的位置&#xff0c;点击执行即可 注意&#xff1a; 导入之后记得刷新一下导出 选择你要导出的数据库 右键选择&#xff1a;备份/导出、…

HDR视频技术之三:色度学与颜色空间

HDR 技术的第二个理论基础是色度学。从前面的内容中可以了解到&#xff0c;光学以及人类视觉感知模型为人类提供了解释与分析人类感知亮度的理论基础&#xff0c;但是 HDR 技术不仅仅关注于提升图像与视频的亮度范围&#xff0c;同时也关注于提供更加丰富的色彩。因此&#xff…

通信与网络安全之IPSEC

IPSec&#xff08;IP Security&#xff09;是IETF制定的为保证在Internet上传送数据的安全保密性能的三层隧道加密协议。IPSec在网络层对IP报文提供安全服务。IPSec协议本身定义了如何在IP数据包中增加字段来保证IP包的完整性、 私有性和真实性&#xff0c;以及如何加密数据包。…

Redis的管道操作

在现代应用程序中&#xff0c;Redis作为一种高性能的内存数据库&#xff0c;被广泛用于缓存、消息队列、实时分析等场景。为了进一步提高Redis的性能&#xff0c;Redis提供了管道&#xff08;Pipeline&#xff09;操作&#xff0c;允许客户端将多个命令一次性发送到服务器&…

67 mysql 的 间隙锁

前言 我们这里主要是 来看一下 mysql 中的 间隙锁 间隙锁 主要存在的地方一般就是在 查询主键查询不到, 索引查询查询不到 的场景 然后 我们这里来调试一下 这里的整个流程, 间隙锁的加锁 以及 间隙锁的使用, 以及 间隙锁的释放 从逻辑上来说 间隙锁 锁定的是一个区间, 按照…

小米PC电脑手机互联互通,小米妙享,小米电脑管家,老款小米笔记本怎么使用,其他品牌笔记本怎么使用,一分钟教会你

说在前面 之前我们体验过妙享中心&#xff0c;里面就有互联互通的全部能力&#xff0c;现在有了小米电脑管家&#xff0c;老款的笔记本竟然用不了&#xff0c;也可以理解&#xff0c;毕竟老款笔记本做系统研发的时候没有预留适配的文件补丁&#xff0c;至于其他品牌的winPC小米…

Apache Zeppelin:一个基于Web的大数据可视化分析平台

今天给大家推荐一下 Apache Zeppelin&#xff0c;它是一个基于 Web 的交互式数据接入、数据分析、数据可视化以及协作文档 Notebook&#xff0c;类似于 Jupyter Notebook。 Apache Zeppelin 支持使用 SQL、Java、Scala、Python、R 等编程语言进行数据处理和分析&#xff0c;同时…

彻底理解如何保证ElasticSearch和数据库数据一致性问题

一.业务场景举例 需求&#xff1a; 一个卖房业务&#xff0c;双十一前一天&#xff0c;维护楼盘的运营人员突然接到合作开发商的通知&#xff0c;需要上线一批热门的楼盘列表&#xff0c;上传完成后&#xff0c;C端小程序支持按楼盘的名称、户型、面积等产品属性全模糊搜索热门…

EasyExcel: 结合springboot实现表格导出入(单/多sheet), 全字段校验,批次等操作(全)

全文目录,一步到位 1.前言简介1.1 链接传送门1.1.1 easyExcel传送门 2. Excel表格导入过程2.1 easyExcel的使用准备工作2.1.1 导入maven依赖2.1.2 建立一个util包2.1.3 ExcelUtils统一功能封装(单/多sheet导入)2.1.4 ExcelDataListener数据监听器2.1.5 ResponseHelper响应值处理…

前端实用知识-用express搭建本地服务器

目录 一、为什么会有这篇文章&#xff1f; 二、使用前的准备-如环境、工具 三、如何使用&#xff1f;-express常用知识点 四、代码演示-配合截图&#xff0c;简单易懂 一、为什么会有这篇文章&#xff1f; 在日常前端开发中&#xff0c;我们离不开数据&#xff0c;可能是用…

Redis(概念、IO模型、多路选择算法、安装和启停)

一、概念 关系型数据库是典型的行存储数据库&#xff0c;存在的问题是&#xff0c;按行存储的数据在物理层面占用的是连续存储空间&#xff0c;不适合海量数据存储。 Redis在生产中使用的最多的是用作数据缓存。 服务器先在缓存中查询数据&#xff0c;查到则返回&#xff0c;…

C#基础控制台程序

11.有一个54的矩阵&#xff0c;要求编程序求出其中值最大的那个元素的值&#xff0c;以及其所在的行号和列号。 12.从键盘输入一行字符&#xff0c;统计其中有多少个单词&#xff0c;单词之间用空格分隔开。 13.输入一个数&#xff0c;判断它是奇数还是偶数&#xff0c;如果…

Flink开发入门简单案例--统计实时流订单

Flink开发入门简单案例 0.简介1.订单数据生成器1.1 新建工程TestFlink1.2 在pom.xml中引入Flink依赖包1.3 订单数据生成类订单类&#xff08;Item&#xff09;订单生成数据流类测试订单生成类 2.订单统计2.1 仅统计订单中商品的件数 2.2 同时统计商品数量和金额 0.简介 本案例…

AI前景分析展望——GPTo1 SoraAI

引言 人工智能&#xff08;AI&#xff09;领域的飞速发展已不仅仅局限于学术研究&#xff0c;它已渗透到各个行业&#xff0c;影响着从生产制造到创意产业的方方面面。在这场技术革新的浪潮中&#xff0c;一些领先的AI模型&#xff0c;像Sora和OpenAI的O1&#xff0c;凭借其强大…

PAT1085 Perfect Sequence(25)

//判断是否是连续的数 //判断是否只能第一个数是最小值 #include <cstdio> #include <algorithm> typedef long long ll; using namespace std; int n,p; const int maxn 100010; int arr[maxn];int binary(int l, int r, ll tgt){if(arr[n-1] < tgt) return n…

QChart数据可视化

目录 一、QChart基本介绍 1.1 QChart基本概念与用途 1.2 主要类的介绍 1.2.1 QChartView类 1.2.2 QChart类 1.2.3QAbstractSeries类 1.2.4 QAbstractAxis类 1.2.5 QLegendMarker 二、与图表交互 1. 动态绘制数据 2. 深入数据 3. 缩放和滚动 4. 鼠标悬停 三、主题 …

SpringBoot源码-spring boot启动入口ruan方法主线分析(一)

一、SpringBoot启动的入口 1.当我们启动一个SpringBoot项目的时候&#xff0c;入口程序就是main方法&#xff0c;而在main方法中就执行了一个run方法。 SpringBootApplication public class StartApp {public static void main(String[] args) {// testSpringApplication.ru…