Linux设备驱动程序 之 主次设备号
主设备号和次设备号
对字符设备的访问是通过文件系统内的设备名称进行的,这些名称被称为特殊文件、设备文件、或者简单称之为文件系统树的节点,它们通常位于/dev目录。字符设备驱动程序的设备文件可以通过ls -l命令输出的第一列中的c字符来识别,块设备也出现在/dev下,但它们由字符b来标识;
通过执行ls -l 命令,可以看到在修改日期之前,有两个用逗号分隔的数字,分别为主设备号和次设备号。
主设备号标识设备对应的驱动程序;linux设备内核允许多个驱动程序共享主设备号;
次设备号由内核使用,用用户正确确定设备文件所指的设备。依赖驱动程序的编写方式,我们可以通过次设备号获得一个指向内核设备的直接指针,也可以将次设备号当做设备本地数组的索引。不管哪种方式,除了知道次设备号用来指向驱动程序所实现的设备之外,内核本身不关心关于此设备号的其他信息;
- crw-rw----. root video , Nov : agpgart
- crw-------. root root , Nov : autofs
- drwxr-xr-x. root root Nov : block
- drwxr-xr-x. root root Nov : bsg
- crw-------. root root , Nov : btrfs-control
- drwxr-xr-x. root root Nov : bus
- lrwxrwxrwx. root root Nov : cdrom -> sr0
- drwxr-xr-x. root root Nov : char
- crw-------. root root , Nov : console
- lrwxrwxrwx. root root Nov : core -> /proc/kcore
- drwxr-xr-x. root root Nov : cpu
- crw-------. root root , Nov : cpu_dma_latency
- crw-------. root root , Nov : cuse
- drwxr-xr-x. root root Nov : disk
- crw-rw----+ root audio , Nov : dmmidi
设备编号的内部表达
内核中,dev_t类型(位于<linux/types.h>)用来保存设备编号,包括主设备号和次设备号;
- typedef __u32 __kernel_dev_t;
- typedef __kernel_dev_t dev_t;
可见dev_t类型是个32位的无符号整数,其中12位用来表示主设备号,其余20位表示次设备号;我们不应该对设备编号的组织做假定,而应该始终使用如下两个宏(位于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))
如果需要将主次设备号转换成dev_t类型,则使用下面宏(位于linux/kdev_t.h):
- #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
分配和释放设备编号
指定范围分配编号:
在建立一个字符设备之前,我们的驱动程序首先要做的事情就是获取一个或者多个设备编号,完成该工作的必要函数是register_chrdev_region,该函数在<linux/fs.h>中声明:
- int register_chrdev_region(dev_t from, unsigned count, const char *name)
参数from标识要分配的设备号范围的起始值,次设备号经常设置为0,但对该函数不是必须的;
参数count标识分配设备号的个数,如果count非常大,则所请求的范围可能和下一个主设备号重叠,但是只要我们所请求的编号范围是可用的,则不会带来问题;
参数name是和该编号范围关联的设备名称,它将出现在/proc/devices和sysfs中;
动态分配设备编号:
在不知道要分配的设备号的时候,可以使用动态分配的方式,函数如下:
- int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
参数dev是仅用于输出的参数,在成功完成调用后将保存已分配范围的第一个编号;
参数baseminor是要使用的被请求的第一个次设备号,通常是0;
参数count标识分配设备号的个数;
参数name是和该编号范围关联的设备名称;
始终使用动态分配设备编号:
对于新的驱动程序,强烈建议不要随便选择一个当前设备未使用的设备号作为主设备号,而应该使用动态分配机制获取主设备号;驱动程序应该使用使用alloc_chrdev_region而不是register_chrdev_region函数;
动态分配的缺点:由于分配的主设备号不能始终保持一致,素以无法预先创建设备节点;对于驱动程序的一般做法是,为了加载一个使用动态主设备号的设备驱动程序,对insmod的调用可替换成一个简单的脚本,该脚本在调用insmod之后读取/proc/devices以获得新分配的主设备号,然后创建对应的设备文件;
释放设备编号:
在不使用设备编号的时候需要进行释放,函数如下:
- void unregister_chrdev_region(dev_t from, unsigned count)
Linux设备驱动程序 之 主次设备号的更多相关文章
- Linux设备驱动程序学习----1.设备驱动程序简介
设备驱动程序简介 更多内容请参考Linux设备驱动程序学习----目录 1. 简介 Linux系统的优点是,系统内部实现细节对所有人都是公开的.Linux内核由大量复杂的代码组成,设备驱动程序可以 ...
- Linux设备驱动程序 之 字符设备的注册
内核内部使用struct cdev结构来标识字符设备,在内核调用设备的操作之前,必须分配并注册一个或者多个上述结构,为此,我们的代码需要包含<linux/cdev.h>,其中定义了这个结构 ...
- Linux串口驱动程序(3)-打开设备
先来分析一下串口打开的过程: 1.用户调用open函数打开串口设备文件:2.在内核中通过tty子系统,把open操作层层传递到串口驱动程序中:3.在串口驱动程序中的xx_open最终实现这个操作.这里 ...
- ARM Linux字符设备驱动程序
1.主设备号和次设备号(二者一起为设备号): 一个字符设备或块设备都有一个主设备号和一个次设备号.主设备号用来标识与设备文件相连的驱动程序,用来反 映设备类型.次设备号被驱动程序用来辨别操作的是哪个 ...
- 如何编写Linux设备驱动程序
一.Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口.设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看 ...
- Linux内核入门到放弃-设备驱动程序-《深入Linux内核架构》笔记
I/O体系结构 总线系统 PCI(Peripheral Component Interconnect) ISA(Industrial Standard Architecture) SBus IEEE1 ...
- 深入理解Linux内核-I/O体系结构和设备驱动程序
系统总线:1.链接CPU.RAM.I/O设备之间的数据流动.例如:PCI.ISA.EISA.MCA.SCSI.USB2.任何I\O设备有且仅能链接一条总线. I\O端口:1.每个连接到I\O总线上的设 ...
- linux设备驱动程序-i2c(0)-i2c设备驱动源码实现
(基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...
- Linux设备驱动程序学习----目录
目录 设备驱动程序简介 1.设备驱动程序简介 构造和运行模块 2.内核模块和应用程序的对比 3.模块编译和装载 4.模块的内核符号表 5.模块初始化和关闭 6.模块参数 7.用户空间编写驱动程序 ...
随机推荐
- 使用jMeter构造大量并发的随机HTTP请求
在前一篇文章使用jMeter构造大量并发HTTP请求进行微服务性能测试里,我介绍了如何用jMeter构造并发HTTP请求.但是通过文中介绍的方式构造的并发请求,其请求参数都是硬编码的'Wang'. 有 ...
- 实时跟踪之TRACA
背景: 目前,在实时跟踪领域存在着越来越多的先进方法,同时也极大地促进了该领域的发展.主要有两种不同的基于深度学习的跟踪方法:1.由在线跟踪器组成,这些跟踪器依赖网络连续的微调来学习目标的变化外观,精 ...
- 前端基础(四):BOM和DOM
前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我们需要继续学习BOM和DO ...
- 4.安装配置bacula-gui(管理页面)
1. 安装配置bacula-gui(管理页面) Bacula-gui分为两个部分: Baculum-api可通过OAuth2(开放认证模式)或HTTP认证(用户名和密码)认证提供统一接口服务: B ...
- php连接oracle oracle开启扩展
<?php /** * 由于公司的需要,使用php+oracle开发项目,oracle因为有专门人员开发设计,我们只需远程调用 *于是乎遇到了蛋疼的问题就是开启oracle扩展的问题,虽然你在p ...
- ARM体系结构与编程读书笔记——处理器的寄存器
ARM处理器共有37个寄存器,其中包括: 31个通用寄存器,包括程序计数器(PC)在内,寄存器都是32位: 6个状态寄存器,这些寄存器都是32位的,目前只使用了其中12位: 通用寄存器 可以分为下面3 ...
- 深度排序模型概述(二)PNN/NFM/AFM
在CTR预估中,为了解决稀疏特征的问题,学者们提出了FM模型来建模特征之间的交互关系.但是FM模型只能表达特征之间两两组合之间的关系,无法建模两个特征之间深层次的关系或者说多个特征之间的交互关系,因此 ...
- iview 表单验证不通过问题?
项目需要,需要怂iview..使用一段时间感觉跟elementUI用起来差不多很方便.使用过程中遇到表单验证问题,如何避免在验证过程中偶尔出现验证不通过的异常情况? <1>:给 <F ...
- 关于C++ Builder Codegurad 问题的排查。
关于C++ BUILDER6 我目前不知道有什么特别好的内存排查工具.尤其为了对付memory leak, (Eurekalog 这个工具内存泄漏主要针对delphi,BCB配置比较繁琐). 除了BC ...
- golang type conversion
map[string]interface{} is not the same as map[string]string. Type interface{} is not the same as typ ...