在为 ioctl 编写代码之前, 你需要选择对应命令的数字. 许多程序员的第一个本能的反 应是选择一组小数从0或1 开始, 并且从此开始向上. 但是, 有充分的理由不这样做. ioctl 命令数字应当在这个系统是唯一的, 为了阻止向错误的设备发出正确的命令而引起 的错误. 这样的不匹配不会不可能发生, 并且一个程序可能发现它自己试图改变一个非串 口输入系统的波特率, 例如一个 FIFO 或者一个音频设备. 如果这样的 ioctl 号是唯一 的, 这个应用程序得到一个 EINVAL 错误而不是继续做不应当做的事情.

为帮助程序员创建唯一的 ioctl 命令代码, 这些编码已被划分为几个位段. Linux 的第 一个版本使用 16-位数: 高 8 位是关联这个设备的"魔"数, 低 8 位是一个顺序号, 在设 备内唯一. 这样做是因为 Linus 是"无能"的(他自己的话); 一个更好的位段划分仅在后 来被设想. 不幸的是, 许多驱动仍然使用老传统. 它们不得不: 改变命令编码会破坏大量 的二进制程序,并且这不是内核开发者愿意见到的.

根据 Linux 内核惯例来为你的驱动选择 ioctl 号, 你应当首先检查 include/asm/ioctl.h 和 Documentation/ioctl-number.txt. 这个头文件定义你将使用 的位段: type(魔数), 序号, 传输方向, 和参数大小. ioctl-number.txt 文件列举了在 内核中使用的魔数,[20]20 因此你将可选择你自己的魔数并且避免交叠. 这个文本文件也列 举了为什么应当使用惯例的原因.

定义 ioctl 命令号的正确方法使用 4 个位段, 它们有下列的含义. 这个列表中介绍的新 符号定义在 <linux/ioctl.h>.

但是, 这个文件的维护在后来有些少见了.

魔数. 只是选择一个数(在参考了 ioctl-number.txt 之后)并且使用它在整个驱动 中. 这个成员是 8 位宽(_IOC_TYPEBITS).

number

序(顺序)号. 它是 8 位(_IOC_NRBITS)宽. direction

数据传送的方向,如果这个特殊的命令涉及数据传送.
可能的值是 _IOC_NONE(没有 数据传输), _IOC_READ, _IOC_WRITE, 和 _IOC_READ|_IOC_WRITE (数据在 2 个方
向被传送). 数据传送是从应用程序的观点来看待的; _IOC_READ 意思是从设备读, 因此设备必须写到用户空间. 注意这个成员是一个位掩码, 因此
_IOC_READ 和

_IOC_WRITE 可使用一个逻辑 AND 操作来抽取.

size

涉及到的用户数据的大小. 这个成员的宽度是依赖体系的, 但是常常是 13 或者 14 位. 你可为你的特定体系在宏 _IOC_SIZEBITS 中找到它的值. 你使用这个 size 成员不是强制的
- 内核不检查它 -- 但是它是一个好主意. 正确使用这个成
员可帮助检测用户空间程序的错误并使你实现向后兼容, 如果你曾需要改变相关数 据项的大小. 如果你需要更大的数据结构, 但是, 你可忽略这个 size 成员. 我们 很快见到如何使用这个成员.

头文件
<asm/ioctl.h>, 它包含在 <linux/ioctl.h> 中, 定义宏来帮助建立命令号, 如 下:
_IO(type,nr)(给没有参数的命令), _IOR(type, nre, datatype)(给从驱动中读数据 的),
_IOW(type,nr,datatype)(给写数据), 和 _IOWR(type,nr,datatype)(给双向传送). type 和 number 成员作为参数被传递,
并且 size 成员通过应用 sizeof 到 datatype 参数而得到.

这个头文件还定义宏, 可被用在你的驱动中来解码这个号: _IOC_DIR(nr),

_IOC_TYPE(nr), _IOC_NR(nr), 和 _IOC_SIZE(nr). 我们不进入任何这些宏的细节,
因为 头文件是清楚的, 并且在本节稍后有例子代码展示.

这里是一些 ioctl 命令如何在 scull 被定义的. 特别地, 这些命令设置和获得驱动的可 配置参数.

/* Use 'k' as magic number */

#define SCULL_IOC_MAGIC 'k'

/* Please use a different 8-bit number in your code */

#define SCULL_IOCRESET _IO(SCULL_IOC_MAGIC, 0)

/*

*  S means
"Set" through a ptr,

*  T means
"Tell" directly with the argument value

*  G means
"Get": reply by setting through a pointer

*  Q means
"Query": response is on the return value

*  X means
"eXchange": switch G and S atomically

*  H means
"sHift": switch T and Q atomically

*/

#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1,
int)

#define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC, 2, int)

#define SCULL_IOCTQUANTUM _IO(SCULL_IOC_MAGIC, 3)

#define SCULL_IOCTQSET _IO(SCULL_IOC_MAGIC, 4)

#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5,
int)

#define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC, 6, int)

#define SCULL_IOCQQUANTUM _IO(SCULL_IOC_MAGIC, 7)

#define SCULL_IOCQQSET _IO(SCULL_IOC_MAGIC, 8)

#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9,
int)

#define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10, int)

#define SCULL_IOCHQUANTUM _IO(SCULL_IOC_MAGIC, 11)

#define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC, 12)

#define SCULL_IOC_MAXNR 14 真正的源文件定义几个额外的这里没有出现的命令.

我们选择实现 2 种方法传递整数参数: 通过指针和通过明确的值(尽管, 由于一个已存在
的惯例, ioclt 应当通过指针交换值). 类似地, 2 种方法被用来返回一个整数值:通过指 针和通过设置返回值. 这个有效只要返回值是一个正的整数; 如同你现在所知道的, 在从 任何系统调用返回时, 一个正值被保留(如同我们在 read 和 write 中见到的), 而一个 负值被看作一个错误并且被用来在用户空间设置 errno.[21] 21

"exchange"和"shift"操作对于 scull 没有特别的用处. 我们实现"exchange"来显示驱动
如何结合独立的操作到单个的原子的操作, 并且"shift"来连接"tell"和"query". 有时需
要象这样的原子的测试-和-设置操作, 特别地, 当应用程序需要设置和释放锁.

命令的明确的序号没有特别的含义. 它只用来区分命令. 实际上, 你甚至可使用相同的序 号给一个读命令和一个写命令, 因为实际的 ioctl 号在"方向"位是不同的, 但是你没有 理由这样做. 我们选择在任何地方不使用命令的序号除了声明中, 因此我们不分配一个返 回值给它. 这就是为什么明确的号出现在之前给定的定义中. 这个例子展示了一个使用命
令号的方法, 但是你有自由不这样做.

除了少数几个预定义的命令(马上就讨论), ioctl 的 cmd 参数的值当前不被内核使用, 并且在将来也很不可能. 因此, 你可以, 如果你觉得懒, 避免前面展示的复杂的声明并明 确声明一组调整数字. 另一方面, 如果你做了, 你不会从使用这些位段中获益, 并且你会 遇到困难如果你曾提交你的代码来包含在主线内核中. 头文件<linux/kd.h> 是这个老式 方法的例子, 使用 16-位的调整值来定义 ioctl 命令. 那个源代码依靠调整数因为使用 那个时候遵循的惯例, 不是由于懒惰. 现在改变它可能导致无理由的不兼容.

linux 选择 ioctl 命令的更多相关文章

  1. 使用Linux的alternatives命令替换选择软件的版本

    上周在安装搜索引擎Elasticsearch时,要求安装比较新的java 版本,我选择了java 1.8.0,安装java 成功后使用java -version 发现使用的版本仍旧是1.6.0, 查询 ...

  2. 关于构造IOCTL命令的学习心得

    在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非 ...

  3. 构造IOCTL命令的学习心得-----_IO,…

    在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非 ...

  4. 例解 Linux 下 Make 命令

    Linux 下 make 命令是系统管理员和程序员用的最频繁的命令之一.管理员用它通过命令行来编译和安装很多开源的工具,程序员用它来管理他们大型复杂的项目编译问题.本文我们将用一些实例来讨论 make ...

  5. 12个Linux进程管理命令介绍(转)

    12个Linux进程管理命令介绍 [日期:2015-06-02] 来源:Linux中国  作者:Linux [字体:大 中 小]   执行中的程序在称作进程.当程序以可执行文件存放在存储中,并且运行的 ...

  6. Linux下rz命令使用的实例详解

    Linux中rz命令和sz命令都可用于文件传输,而rz命令主要用于文件的上传,下面将通过几个实例来给大家详细介绍下Linux下rz命令的用法,一起来学习下吧. rz命令可以批量上传文件,当然也可上传单 ...

  7. linux 的 scp 命令 可以 在 linux 之间复制 文件 和 目录

    转自:http://blog.csdn.net/snlying/article/details/6184102 Linux系统中scp命令的用法. scp就是secure copy的简写,用于在lin ...

  8. 从零单排Linux – 1 – 简单命令

    从零单排Linux – 1 – 简单命令 Posted in: Linux 从零单排Linux – 1 一.Linux的简单命令: 1.忘记root密码: 读秒时按任意键进入 – e – ↓选择第二个 ...

  9. linux中screen命令的用法

    http://www.9usb.net/201002/linux-screen-mingling.html 作为linux服务器管理员,经常要使用ssh登陆到远程linux机器上做一些耗时的操作.也许 ...

随机推荐

  1. hpacucli工具linux系统下重做阵列

    需要安装hpacucli-8.0-14.noarch.rpm 这个工具 hpacucli ctrl all show   查看卡位  图上slot 2 下面命令上要使用到的 查看硬盘类型 hpacuc ...

  2. linux 下配置多个tomcat同时运行

    一个服务器上内存通常有2G或者更多,一个tomcat 运行管理这么多内存有点力不从心,并且貌似一个进程所能建立的线程数量是有限的,于是我们想要在一个服务器上运行多个tomcat.如下是摘抄自:http ...

  3. 【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵

    题目描述 他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术.热情周到的服务赢得了广大客户的尊敬和赞美.他就是老百姓称为"李电"的李春来. 众所周知, ...

  4. 【JZOJ4755】【NOIP2016提高A组模拟9.4】快速荷叶叶变换

    题目描述 输入 一行,包含两个整数N,M. 输出 1个整数,FHT(N,M) mod 1000000007的值. 样例输入 3 4 样例输出 1 数据范围 对于 40% 的数据,1 ≤ N,M ≤ 1 ...

  5. D3D10/11中的遮挡查询的使用

    原文:D3D10/11中的遮挡查询的使用       在D3D10/11中,有D3D10_QUERY/D3D11_QUERY接口,通过QUERY接口,我们可以查询GPU的一些状态,比如GPU的时间戳信 ...

  6. CSS user-select文本是否可复制

    1. 概述 1.1 说明 在项目过程中,有时候需要网页中内容信息不可被复制进行保护数据信息,故可使用css属性user-select进行控制用户能否选中文本. 1.2 语法 user-select : ...

  7. jQuery自动过滤单词插件

    在线演示 本地下载

  8. Java中的四种引用(强引用、软引用、弱引用、虚引用)

    以下内容摘自<深入理解Java虚拟机 JVM高级特性与最佳实践>第2版,强烈推荐没有看过的同学阅读,读完的感觉就是"原来学的都是些什么瘠薄东西(╯‵□′)╯︵┴─┴" ...

  9. @划水记@ THUWC2020 (?)

    目录 @day -1@ @day 0@ @day 1@ @day 2@ @day 2+@ @day 3@ @day ?@ @day -1@ 听闻 THUWC 在 12 月举行的消息,突然就停了大概一周 ...

  10. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照 代码工程地址: https://github.com/j ...