ioctl函数是否使用32位指针?64位内核模块下为何无运行问题?
ioctl 回调参数类型与64位兼容性问题解答
首先给出内核中file_operations结构体对应的ioctl回调定义:
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
关于unsigned long参数是否为32位指针的疑问
这里的unsigned long类型完全不代表ioctl固定使用32位指针,原因如下:
- Linux内核中选择
unsigned long作为该参数的类型,核心是利用该类型和当前架构地址位宽完全对齐的特性:- 32位架构编译时,
unsigned long占4字节,刚好可以容纳32位指针 - 64位架构编译时,
unsigned long占8字节,刚好可以容纳64位指针
- 32位架构编译时,
- 这个参数本质是通用参数容器,既可以传递指针,也可以传递整型数值,使用时只需要按照预定义的ioctl命令规则做强制类型转换即可,不会固定按32位处理
64位内核编译无问题的原因
- 内核模块编译时会自动继承目标内核的编译参数,
unsigned long的位宽会和内核本身的位宽完全匹配,用户空间传入的指针在进入系统调用时,会被正确赋值到该参数中,不会出现指针截断、信息丢失的问题 - 如果存在32位用户态程序访问64位内核的兼容场景,内核会通过单独的
compat_ioctl回调处理32位指针的转换逻辑,原有的ioctl回调只会处理和内核位宽一致的调用请求,不会出现位宽不匹配的问题
内容的提问来源于stack exchange,提问作者Harry Muscle
相关产品推荐
相关产品推荐

