1.什么是ioctl
ioctl是用于设备(文件或者套接字)控制的公共接口,除了读取和写入设备之外,大部分驱动程序还需要另外一种能力,即通过设备驱动程序执行各种类型的硬件控制。简单数据传输外,大部分设备可以执行其他一些操作,比如,用户空间经常会请求设备状态,弹出设备,报告错误信息,改变波特率或者执行自破坏,等。这些操作通常通过ioctl方法执行,该方法实现了同名的系统调用。
2.ioctl
2.1 函数原型
在用户空间,ioctl系统调用原型如下:
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
参数中使用的…表示可变数码的参数,但是在实际系统找中,系统调用不会真正使用可变数目的参数,而是必须具有精确定义的原型。
2.2 参数说明
int d
该参数是SOCK_DGRAM类型的套接字,一般初始化方式为:
sock = socket(AF_INET, SOCK_DGRAM, 0);
int request
该参数是请求命令编号。这些编号一部分是已经编订好的,另外一部分是用户自己通过调用系统接口宏编制的。早期的Linux版本,为了方便程序员创建唯一的ioctl命令号,每一个命令号划分为多个位字段,Linux第一个版本使用一个16 bit的无符号整数。高8 bit是与设备相关的幻数,地8位是一个序列号嘛,在该设备内唯一。
已经编码好的命令,可以参考文件kernel/Documentation/ioctl/ioctl-number.txt中的说明,下面列举出对私有设备的编码:
0x89 00-06 arch/x86/include/asm/sockios.h
0x89 0B-DF linux/sockios.h
0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
0x89 E0-EF linux/dn.h PROTOPRIVATE range
0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
对于比较新的设备的请求命令编码,或者是用户自己添加的某类设备(比如 gpio)命令编码,则使用32 bit的请求码,这32位的编码有对应的规则:
bits meaning
31-30 00 - no parameters: uses _IO macro
10 - read: _IOR
01 - write: _IOW
11 - read/write: _IOWR
29-16 size of arguments
15-8 ascii character supposedly,unique to each driver
7-0 function #
kernel中提供宏接口用于计算出唯一的命令请求码
#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))
常见的16bit的命令编码在文件kernel\include\linux\socketios.h中定义:
/* Socket configuration controls. */
#define SIOCGIFNAME 0x8910 /* get iface name*/
#define SIOCSIFLINK 0x8911 /* set iface channel */
#define SIOCGIFCONF 0x8912 /* get ifa