ioctl

一、 什么是ioctl。

除了读取和写入设备之外,大部分驱动程序还需要通过设备驱动程序实行各种类型的硬件控制。简单的数据传输之外,大部分设备还可以执行其他一些操作,比如,用户空间经常会请求设备锁门,弹出介质,报告错误信息,改变波特率或者执行子破坏,等等。这些操作通常通过ioctl方法来支持。 

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:

int ioctl(int fd, int cmd, …);

     其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。

ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。

二、 ioctl的必要性

     如果不用ioctl的话,也可以实现对设备I/O通道的控制。例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。

     所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

三、 ioctl如何实现

在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事情,因为设备都是特定的,这里也没法说。关键在于怎么样组织命令码,因为在ioctl中命令码是唯一联系用户程序命令和驱动程序支持的途径。

命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不会将正确的命令发给错误的设备,或者是把错误的命令发给正确的设备,或者是把错误的命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程序员发现了这些奇怪的事情的时候,再来调试程序查找错误,那将是非常困难的事情。

所以在Linux核心中是这样定义一个命令码的:

____________________________________

| 设备类型 | 序列号 | 方向 |数据尺寸|

|----------|--------|------|--------|

| 8 bit    |  8 bit |2 bit |8~14 bit|

|----------|--------|------|--------|

这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数据传送方向和数据传输尺寸。

例如:内核中给出了创建ioctl命令的宏

/* used to create numbers */
#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)))     //双向
#define _IOR_BAD(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

再多说一个地方,那就是"幻数"。

幻数是一个字母,数据长度也是8,所以就用一个特定的字母来标明设备类型,这和用一个数字是一样的,只是更加利于记忆和理解。即:设备类型

推荐各位阅读《Linux 设备驱动程序》所带源代码中的short一例,因为它比较短小,功能比较简单,可以看明白ioctl的功能和细节。

 

转载:http://blog.chinaunix.net/uid-26681200-id-3170897.html

Linux ioctl(Input Output Control)是一组特殊的系统调用,用于控制设备驱动程序的状态或功能,以便进行低级别的I/O操作。这些操作对于直接与硬件交互非常有用,例如改变USB设备的配置、调整串口通信参数或是对网络适配器进行更细致的控制。 ioctl的基本语法形式是一个整数值,这个值包含两部分信息: 1. **主要编号**(通常是大写字母M):标识 ioctl 的用途类别。 2. **次要编号**(通常是小写字母m):进一步细分具体的 ioctl 操作。 例如 `IOCTL_MDEV` 可能表示某一种设备驱动的相关指令集,`IOCTL_MDEV_SET_SPEED` 则是一个具体的指令,用于设置某个设备的速度。 典型的 ioctl 调用看起来像这样: ```c int ioctl(int fd, unsigned long request, ...); ``` 这里的参数解释如下: - `fd`:文件描述符,关联到设备或文件的一个索引,通常由 open 或其他 I/O 函数返回。 - `request`:一个由驱动程序特定的长整型值,包含指令和可能的数据。 - `...`:额外的数据,取决于请求的具体内容。 ioctl 的应用例子很多,比如在网络编程中调整套接字选项,或者在音频硬件编程中控制混音器的状态。它们之所以重要是因为它们让应用程序能够以比标准 I/O 更底层的方式控制设备,从而提高性能或实现特定功能。 了解 ioctl 的使用可以帮助开发者深入理解系统级别的细节,以及更好地优化他们的程序与硬件的交互。 --- 相关问题 - : 1. ioctl 与其他 I/O 控制方式的区别是什么? 2. 在实际编程中如何正确地使用 ioctl 进行设备控制? 3. 对于不同的硬件设备(如 USB 设备、串口、网络设备),常见的 ioctl 请求有哪些?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值