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

bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。

bit29~bit16 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内存大小。

bit15~bit08  8位为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。

bit07~bit00   8位为 "区别序号" 区,是区分命令的命令顺序序号。

内核定义了 _IO() , _IOR() , IOW() 和 _IOWR() 这 4 个宏来辅助生成上面的 cmd

#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))

命令码中的 “区分读写区” 里的值可能是 _IOC_NONE (0值)表示无数据传输,_IOC_READ (读), _IOC_WRITE (写) , _IOC_READ|_IOC_WRITE (双向)。

#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT)) #define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) #define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
# define _IOC_SIZEBITS 14

宏展开后

#define _IO(type,nr)			(((_IOC_NONE)  << 30) | ((0) << 16)) | ((type) << 8) | ((nr)   << 0)

(dir)  << _IOC_DIRSHIFT)    dir 往左移 30 位,即移到 bit31~bit30 两位上,得到方向(读写)的属性;
(size) << _IOC_SIZESHIFT)   size左移 16 位得到“数据大小”区;

(type) << _IOC_TYPESHIFT)   type左移 8位得到"魔数区" ;

(nr)   << _IOC_NRSHIFT)     nr左移 0 位( bit7~bit0) "得到基数区";

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

魔数 (magic number)

魔数范围为 0~255 。通常,用英文字符 "A" ~ "Z" 或者 "a" ~ "z" 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助状态。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。设备驱动程序获取魔数:

_IOC_TYPE (cmd) 

基(序列号)数

基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读取和写入命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时 使用 switch ,且直接使用命令变量 cmd值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序获取该基数:

_IOC_NR (cmd) 

变量型

变量型使用 arg 变量指定传送的数据大小,但是不直接代入输入,而是代入变量或者是变量的类型,原因是在使用宏创建命令,已经包含了 sizeof() 编译命令。比如 _IOR() 宏的定义是:

#define _IOR(type,nr,size)    _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))

而_IOC_TYPECHECK() 的定义正是:

#define _IOC_TYPECHECK(t) (sizeof(t))

设备驱动程序想要从传送的命令获取相应的值,就要使用下列宏函数: 

_IOC_SIZE(cmd) 

_IO 宏

该宏函数没有可传送的变量,只是用于传送命令。例如如下约定:

#define TEST_DRV_RESET _IO ('Q', 0)

此时,省略由应用程序传送的 arg 变量或者代入 0 。在应用程序中使用该宏时,比如:

ioctl (dev, TEST_DEV_RESET, 0) 或者  ioctl (dev, TEST_DRV_RESET) 。 

这是因为变量的有效因素是可变因素。只作为命令使用时,没有必要判 断出设备上数据的输出或输入。因此,设备驱动程序没有必要执行设备文件大开选项的相关处理。

_IOR 宏

该函数用 于创建从设备读取数据的命令,例如可如下约定:

#define TEST_DEV_READ  _IRQ('Q', 1, int)

这说明应用程序从设备读取数据的大小为 int 。下面宏用于判断传送到设备驱动程序的 cmd 命令的读写状态:

_IOC_DIR (cmd) 

运行该宏时,返回值的类型 如下: 

_IOC_NONE                             :  无属性

_IOC_READ                             :  可读属性

_IOC_WRITE                            : 可写属性

_IOC_READ | _IOC_WRITE : 可读,可写属性

使用该命令时,应用程序的 ioctl() 的 arg 变量值指定设备驱动程序上读取数据时的缓存(结构体)地址。

_IOW 宏

用于创建设 备上写入数据的命令,其余内容与 _IOR 相同。通常,使用该命令时,ioctl() 的 arg 变量值指定设备驱动程序上写入数据时的缓存(结构体)地址。

_IOWR 宏

用于创建设备上读写数据的命令。其余内 容与 _IOR 相同。通常,使用该命令时,ioctl() 的 arg 变量值指定设备驱动程序上写入或读取数据时的缓存 (结构体) 地址。

Linux IO控制命令生成的更多相关文章

  1. linux IO诊断命令集

    IO.sh ##iostat是查看磁盘活动统计情况 ##显示全部设备负载情况 r/s: 每秒完毕的读 I/O 设备次数.即 rio/s:w/s: 每秒完毕的写 I/O 设备次数.即 wio/s等 io ...

  2. linux进程控制命令

    & 加在一个命令的最后,可以把这个命令放到后台执行 ,如gftp &. ctrl + z 可以将一个正在前台执行的命令放到后台,并且处于暂停状态,不可执行. jobs 查看当前有多少在 ...

  3. Linux中IO监控命令的使用分析

    一篇不错的有关linux io监控命令的介绍和使用. 1.系统级IO监控 iostat iostat -xdm 1    # 个人习惯 %util         代表磁盘繁忙程度.100% 表示磁盘 ...

  4. Linux 视频设备驱动V4L2最常用的控制命令

    http://blog.csdn.net/shaolyh/article/details/6583226 Linux 视频设备驱动V4L2最常用的控制命令使用说明(1.02) 命令 功能 VIDIOC ...

  5. 自学Linux Shell15.2-作业控制命令(jobs/bg/nice/renice/at/atp/atrm/crontab)

    点击返回 自学Linux命令行与Shell脚本之路 15.1-作业控制命令(jobs/bg/nice/renice/at/atp/atrm/crontab) 1  控制作业 1.1查看作业 (jobs ...

  6. linux io的cfq代码理解

    内核版本: 3.10内核. CFQ,即Completely Fair Queueing绝对公平调度器,原理是基于时间片的角度去保证公平,其实如果一台设备既有单队列,又有多队列,既有快速的NVME,又有 ...

  7. Linux IO性能分析blktrace/blk跟踪器

    关键词:blktrace.blk tracer.blkparse.block traceevents.BIO. 本章只做一个记录,关于优化Block层IO性能方法工具. 对Block层没有详细分析,对 ...

  8. Linux 项目实用命令

    总结一下Linux下常用的命令 nc nc命令,这是Linux一般都带有的,被誉为“瑞士军刀”.windows和Linux都有,可以下载安装对应的平台工具.使用UDP和TCP协议的网络连接去读写数据, ...

  9. 深入剖析Linux IO原理和几种零拷贝机制的实现

    深入剖析Linux IO原理和几种零拷贝机制的实现 来源 https://zhuanlan.zhihu.com/p/83398714 零壹技术栈      公众号[零壹技术栈] 前言 零拷贝(Zero ...

随机推荐

  1. Java获取.properties配置文件某一项value根据key值

    public static String getProperty(String key){ InputStream in = PropertiesUtils.class.getResourceAsSt ...

  2. jquery+html三级联动下拉框

    jquery+html三级联动下拉框及详情页面加载时的select初始化问题   html写的三个下拉框,如下: <select name="ddlQYWZYJ" id=&q ...

  3. js实现文字横向滚动

    页面布局      <div id="scroll_div" class="fl">         <div id="scroll ...

  4. jQuery弹出窗口完整代码

    jQuery弹出窗口完整代码 效果体验:http://keleyi.com/keleyi/phtml/jqtexiao/1.htm 1 <!DOCTYPE html PUBLIC "- ...

  5. javascript保留两位

    原文:javascript保留两位 //保留两位小数 //功能:将浮点数四舍五入,取小数点后2位 function toDecimal(x) { var f = parseFloat(x); if ( ...

  6. DDD领域驱动设计

    DDD领域驱动设计实践篇之如何提取模型 需求说明: 省级用户可以登记国家指标 省级用户和市级用户可以登记指标分解 登记国家指标时,需要录入以下数据:指标批次.文号.面积,这里省略其他数据,下同 登记指 ...

  7. Oracle表介绍--簇表

    簇和簇表       簇其实就是一组表,是一组共享相同数据块的多个表组成. 将经常一起使用的表组合在一起成簇可以提高处理效率.       在一个簇中的表就叫做簇表.建立顺序是:簇→簇表→数据→簇索引 ...

  8. ps入门教程:裁剪工具、修复画笔工具、图章工具的使用

    本节课程主要内容:学习裁剪工具.污点修复画笔工具.修复画笔工具.修补工具.套索工具.红眼工具.仿制图章工具和图案图 章工具的应用.----------------------------------- ...

  9. 使用EasyUI的树控件构建Web界面

    最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采用EasyUI的前端界面处理技术,走MVC的技术路线,在重 ...

  10. c#后台输出javascript语句和一些通用验证的类

    大家在用MVC的时候,经常会用到MODEL层的验证或者是正则表达式,我这边看到了一篇不错的文章,转载过来http://blog.csdn.net/accpxcb/article/details/311 ...