Linux系统中如何获取_IOWR宏定义的IOCTL_NAME对应的IOCTL编号
IOCTL编号计算方法
Linux系统下ioctl编号是32位整数,由_IOWR这类宏按固定规则拼接生成,计算逻辑如下:
1. 先明确ioctl编号的4个组成字段(主流x86/ARM架构规则)
- 方向位(2位,最高2位):标识数据传输方向,
_IOWR对应读写双向,取值为_IOC_READ | _IOC_WRITE = 2 | 1 = 3 - 大小位(14位,方向位之后的14位):标识传输参数的字节大小,等于
sizeof(ioctl_param)的结果 - 魔数位(8位,大小位之后的8位):你定义的
IOCTL_MAGIC为字符'A',对应ASCII码十进制65、十六进制0x41 - 序号位(8位,最低8位):你传入的功能序号2,对应值为0x2
2. 宏拼接逻辑
内核中_IOWR的底层展开规则为:
// 内核标准宏定义 #define _IOC(dir, type, nr, size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOWR(type, nr, size) _IOC(_IOC_READ|_IOC_WRITE, (type), (nr), sizeof(size))
其中默认移位偏移值为:_IOC_DIRSHIFT=30、_IOC_SIZESHIFT=16、_IOC_TYPESHIFT=8、_IOC_NRSHIFT=0
3. 实际计算示例
假设你定义的ioctl_param类型大小为16字节,计算过程为:
- 方向位部分:
3 << 30 = 0xC0000000 - 大小位部分:
16 << 16 = 0x00100000 - 魔数位部分:
65 << 8 = 0x00004100 - 序号位部分:
2 << 0 = 0x00000002
将四个部分按位或得到最终值:0xC0000000 | 0x00100000 | 0x00004100 | 0x00000002 = 0xC0104102
快速获取准确值的方法
如果不想手动计算避免出错,可以直接在C代码中添加打印语句编译运行即可得到真实值:
#include <stdio.h> // 此处引入你定义IOCTL_NAME的头文件 int main() { printf("IOCTL_NAME 对应编号为:0x%x\n", IOCTL_NAME); return 0; }
内容的提问来源于stack exchange,提问作者MicrosoctCprog
相关产品推荐
相关产品推荐

