linux驱动学习(七) ioctl中的cmd和_IO() , _IOR() , IOW() ,_IOWR() 以及_IOC_NR()的关系

理解_IOR、_IOW、_IOWR宏作用:快速理解手册 通过分析_IOR、_IOW、_IOWR宏的定义与实现,揭示其在驱动开发中构造ioctl命令码的关键作用,帮助开发者快速掌握硬件控制接口的设计逻辑。 阅读详情

以下部分内容来自互联网

在驱动程序里, ioctl() 函数传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。

ioctl()的cmd可以通过使用宏_IO()得到,那么cmd到底是怎么组成的呢?

cmd的大小为 32位,共分 4 个域:

bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。
bit29~bit15 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内存大小。
bit20~bit08  8位为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。
bit07~bit00   8位为 "区别序号" 区,是区分命令的命令顺序序号。
像命令码中的 “区分读写区” 里的值可能是 _IOC_NONE (0值)表示无数据传输,_IOC_READ (读), _IOC_WRITE (写) , _IOC_READ|_IOC_WRITE (双向)。
内核定义了 _IO() , _IOR() , IOW() 和 _IOWR() 这 4 个宏来辅助生成上面的 cmd 。下面分析 _IO() 的实现,其它的类似。
在 asm-generic/ioctl.h 里可以看到 _IO() 的定义:
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
再看 _IOC() 的定义:
#define _IOC(dir,type,nr,size) \
    (((dir)  << _IOC_DIRSHIFT) | \
     ((type) << _IOC_TYPESHIFT) | \
     ((nr)   << _IOC_NRSHIFT) | \
     ((size) << _IOC_SIZESHIFT))
可见,_IO() 的最后结果由 _IOC() 中的 4 个参数移位组合而成。
再看 _IOC_DIRSHIT 的定义:
#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT+_IOC_SIZEBITS)
_IOC_SIZESHIFT 的定义:
#define _IOC_SIZESHIFT    (_IOC_TYPESHIFT+_IOC_TYPEBITS)
_IOC_TYPESHIF 的定义:
#define _IOC_TYPESHIFT    (_IOC_NRSHIFT+_IOC_NRBITS)
_IOC_NRSHIFT 的定义:
#define _IOC_NRSHIFT    0
_IOC_NRBITS 的定义:
#define _IOC_NRBITS    8
_IOC_TYPEBITS 的定义:
#define _IOC_TYPEBITS    8
由上面的定义,往上推得到:
_IOC_TYPESHIFT = 8
_IOC_SIZESHIFT = 16
_IOC_DIRSHIFT = 30
所以,(dir)  << _IOC_DIRSHIFT) 表是 dir 往左移 30 位,即移到 bit31~bit30 两位上,得到方向(读写)的属性;
            (size) << _IOC_SIZESHIFT) 位左移 16 位得到“数据大小”区;
            (type) << _IOC_TYPESHIFT) 左移 8位得到"魔数区" ;
           (nr)   << _IOC_NRSHIFT)      左移 0 位( bit7~bit0) 。
这样,就得到了 _IO() 的宏值。

所以在应用程序中调用ioctl()一般是这样的:

#define I2C_IOCTL_CMD_MAKE(cmd)     ( _IO( I2C_DRV_MAGICNUM, cmd) )

cmd = I2C_IOCTL_CMD_MAKE(I2C_CMD_WRITE);
status = ioctl(hndl->fd, cmd, &prm);

在对应的驱动程序中在switch对cmd做出分类时有这样的调用:

#define I2C_IOCTL_CMD_GET(cmd)      ( _IOC_NR(cmd) )
#define I2C_IOCTL_CMD_IS_VALID(cmd) ( (_IOC_TYPE(cmd) == I2C_DRV_MAGICNUM ) ? 1 : 0)

if(!I2C_IOCTL_CMD_IS_VALID(cmd))
    return -1;
cmd = I2C_IOCTL_CMD_GET(cmd);
switch(cmd)
{}

那么_IOC_NR()和_IOC_TYPE()又是什么东西,从形式上看应该是_IO()的逆操作


以上几个宏的使用格式为:
_IO (魔数, 基数);
_IOR (魔数, 基数, 变量型)
_IOW  (魔数, 基数, 变量型)
_IOWR (魔数, 基数,变量型 )

魔数 (magic number)
魔数范围为 0~255 。通常,用英文字符 "A" ~ "Z" 或者 "a" ~ "z" 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助状态。设备驱动程序可以通过 _IOC_TYPE (cmd)来获取魔数。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。
基(序列号)数
基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读取和写入命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时使用 switch ,且直接使用命令变量 cmd值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序想要从命令中获取该基数,就使用下面的宏:
_IOC_NR (cmd)
通常,switch 中的 case 值使用的是命令的本身。
变量型
变量型使用 arg 变量指定传送的数据大小,但是不直接代入输入,而是代入变量或者是变量的类型,原因是在使用宏创建命令,已经包含了 sizeof() 编译命令。

【Linux源码阅读】Linux内核_IO宏   Linux内核_IO宏主要用于创建实现驱动接口“ioctl()”传递的命令变量(cmd),使用改宏可以区别应用程序传入的cmd请求方式和内容,如数据传递方向、可读、可写等。 1.命令码   在使用_IO宏之前,有必要知道ioctl传递命令码(cmd)含义。Linux内核定义了cmd值是以一个32bit的整型数表示,把32bit划分为4块区域,每块区域表示不同的含义,如图表示。 【1】bi... 阅读详情

相关推荐

ViViT视频分类实战:从Tubelet Embedding到4种Attention变体的保姆级解析

本文深入解析ViViT(Video Vision Transformer)在视频分类中的实战应用,重点介绍Tubelet Embedding技术和4种Attention变体的实现细节。通过对比分析Spatio-Temporal、Factorised Encoder等不同Attention机制的性能特点,提供工程优化策略和Kinetics数据集上的实战示例,帮助开发者掌握这一前沿视频理解技术。

weixin_29292535的博客 386

[转] ioctl的命令cmd构造详解

转自:http://blog.youkuaiyun.com/helloanthea/article/details/25330809。 0 前言 之前对ioctl的cmd认知是:只要保证应用程序传入的与驱动程序定义的cmd一致即可。但是最近在开发某驱动程序过程中发现不是如此。当试图传入的命令字是0x0000_0002时,出现了Bad Address的错误,而且根本没有进入驱动程序定义的ioctl方法(

FireBird的专栏 3107

PCB布线避坑指南:晶振布局的5个致命错误(附正确示例图)

本文深入解析PCB布线中晶振布局的5个致命错误,包括底层布线、电容布局、地平面处理等关键问题,并提供实战解决方案。通过真实案例和量化数据,帮助硬件开发者避免常见陷阱,提升电路稳定性和性能。特别针对晶振这一高敏感元件,给出布线参数黄金法则和三维避让原则。

weixin_29215391的博客 428

【5】字符设备ioctl操作

字符设备的ioctl操作

哈哈一笑 3143

保姆级教程:手把手教你下载和配置Waymo自动驾驶数据集(附百度网盘链接)

本文提供了一份详细的Waymo自动驾驶数据集下载和配置指南,特别针对国内研究者优化了数据获取方案,包括百度网盘链接和Google Cloud CLI配置。文章还涵盖了环境配置、数据处理实战、可视化分析以及进阶技巧,帮助开发者高效利用这一业界黄金标准数据集进行自动驾驶研究。

weixin_42651281的博客 363

避开这些坑!RK3588安卓系统内置输入法的正确姿势(含.mk文件修改指南)

本文详细解析了在RK3588安卓系统定制中预置第三方输入法的完整流程与关键避坑指南。重点涵盖APK签名、Android.mk文件编写、系统默认输入法配置(使用adb ime list命令获取服务名)以及SeLinux策略适配等核心步骤,并指出RK3566/RK3568等兄弟平台的通用性与差异点,帮助开发者实现稳定、深度的系统集成。

tgb34567890的博客 437

驱动中有关ioctl[宏]_IO, _IOR, _IOW, _IOWR 宏的用法与解析

在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域: bit31~bit302位为 “区别读写” 区,作用是区分是读取命令还是写入命令。 bit29~bit1514位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内存...

阿Sir问道 2484

告别编译报错!STC32G12K128在Keil C251下的完整Target配置指南(附ROM设置详解)

本文详细介绍了STC32G12K128在Keil C251下的完整Target配置指南,包括ROM设置、CPU模式选择、内存模型优化等关键步骤。通过实战技巧和常见错误解决方案,帮助开发者高效搭建编译环境,避免常见报错,充分发挥STC32G系列芯片的性能优势。

weixin_29186249的博客 339

Linux之设备控制接口(ioctl)

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。对I/O通道进行管理,就是对设备的一些特性进行控制。虽然在文件操作结构体struct file_operations中有很多对应的设备操作函数,但是有些命令是实在找不到对应的操作函数,拓展一些file_operations给出的接口中没有的自定义功能,则需要使用到ioctl()函数。如CD-ROM的驱动,想要一个弹出光驱的操作,这种操作并不是所有的字符设备都需要的,所以文件操作结构体也不会有对应的函数操作。

风间琉璃的博客 4288

时序预测 | MATLAB实现NGM(1,1)多变量灰色时间序列预测

时序预测 | MATLAB实现NGM(1,1)多变量灰色时间序列预测

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 1514

【100%通过率】华为OD机试真题 Python 实现【网上商城优惠活动 / 模拟商场优惠打折II】

某网上商场举办优惠活动,发布了满减、打折、无门槛3种 优惠券,分别为: 1:每满100元优惠10元,无使用数限制,如100~199元可以使用1张减10元,200~299可使用2张减20元,以此类推; 2:92折券,1次限使用1张,如100元,则优惠后为92元, 3:无门槛5元优惠券,无使用数限制,直接减5元。

MISAYAONE的博客 9371

Linux驱动编程 - _IO, _IOR, _IOW, _IOWR 宏的用法与解析

Linux驱动中 _IO, _IOR, _IOW, _IOWR 宏的用法

hinewcc的博客 1544

手把手教你学Simulink实例--使用 Simulink 进行电力电子系统的小信号模型仿真

电力电子系统(Power Electronics System)包括各种功率转换器(如 DC-DC 转换器、逆变器等)。这些设备中的关键组件(如 MOSFET、IGBT、电容器、电感器等)不仅影响系统的性能,还直接关系到系统的稳定性、效率和可靠性。因此,在设计阶段进行详细的建模和仿真至关重要。小信号模型仿真的目的是通过线性化非线性系统来评估其动态特性,包括增益、相位裕度、带宽等指标。通过本教程,我们介绍了如何使用 Simulink 进行电力电子系统的小信号模型仿真。背景介绍。

MHD0815的博客 298

Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析

Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析

weixin_45795497的博客 4380

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IOCTL命令-_IO, _IOR, _IOW, _IOWR 幻数的理解

有一年半时间没有一行一行的写过linux驱动程序了,有的东西会发现遗忘了,今天就当是复习一下吧。 在编写ioctl代码之前,需要选择对应不同命令的编号。为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非串行设备输入流修改波特率,如果每一个ioctl命令都是唯一的,应用程序进行这种操作时就会得到一个

koozxcv的博客 2419

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

linux驱动—— ioctl中的cmd和_IO() , _IOR() , IOW() ,_IOWR() 以及_IOC_NR()的关系

在驱动程序里, ioctl() 函数传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 ioctl()的cmd可以通过使用宏_IO()得到,那么cmd到底是怎么组成的呢? cmd的大小为 32位,共分 4 个域: bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。 bit29~bit

manchestermi的博客 1750

IOCTL命令格式解析以及调用过程

一、IOCTL的系统调用 1、应用程序中的ioctl(系统IO的内容) #include int ioctl(int d, int request, ...); 应用程序向驱动程序发送命令(cmd),然后应用程序可以向驱动程序发送数据(args),也可以从驱动程序中读数据。 2、驱动程序中,对应的ioctl struct file_operations { struct module *owner; int (*ioctl) (struct inode *inode, struct f

jinking01的专栏 5883

ioctl之关联_IO, _IOR, _IOW, _IOWR 宏的用法与解析

在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域: bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。 bit29~bit16 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送

HULIHONG的专栏 1126

Linux驱动学习—ioctl接口

unlocked_ioctl 实际上取代了用了很久的ioctl,主要的改进就是不再需要上大内核锁(BKL) (调用之前不再先调用lock_kernel()然后再unlock_kernel())。值得注意的是,内核中使用的合成宏和分解宏与应用层使用的是一样的。其实可以用户和内核空间共用的头文件,里面是ioctl命令的构成和头文件。和open read write函数同理,当在应用层代码中调用ioctl接口的时候,其实调用的内核file_operations的unlocked_ioctl结构体成员。

suifen_的博客 1722

_IO, _IOR, _IOW, _IOWR 宏的用法与解析

在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域: bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。 bit29~bit15 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内存大小。 bit20~bit08 8位为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序

reille的笔记 2007

ioctl中的cmd和_IO() , _IOR() , IOW() ,_IOWR() 以及_IOC_NR()的基情

在驱动程序里, ioctl() 函数传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 ioctl()的cmd可以通过使用宏_IO()得到,那么cmd到底是怎么组成的呢? cmd的大小为 32位,共分 4 个域: bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。 bit29~bit

qigaojian的专栏 703

linux驱动--ioctl接口

内核中对底层设备操作完全可以通过read、write接口来实现,在linux 2.2之前都是没有ioctl接口的,2.4以后才引入ioctl接口。 典故(据说),以前在操作软盘时,需要弹出光盘时命令为eject,可以通过write写这个字符串来传输这个指令,但是此时,如果要往软盘中写入”eject”字符串时就出现了歧义的问题。虽然可以通过附加一些代码绕过这个问题,但是不是严谨的开发者的习惯。所以

xiaohuima_dong的专栏 1358

从入门到实战:Linux GPIO_LED 驱动开发(ioctl 接口实现)

本文介绍了嵌入式Linux中通过ioctl接口控制LED的驱动开发流程。ioctl是Linux内核提供的设备控制接口,支持"命令+数据"交互方式,适合LED等外设控制。文章详细解析了ioctl命令码的32位组成结构,包括传输方向、数据大小、魔数和命令编号。开发流程涉及杂项设备注册、GPIO操作和ioctl命令交互等核心内容,配套代码可直接编译运行,帮助初学者快速掌握GPIO外设开发技能。

Arockdj的博客 1511
上一篇: /proc/devices awk
下一篇: linux驱动学习(八) i2c驱动架构(史上最全) davinc dm368 i2c驱动分析
ghostyu
博客等级 码龄18年 1040粉丝 88原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值