Linux ioctl
定义和兼容性层是一个令人着迷的话题,我刚刚对此进行了猛烈的抨击。
通常ioctl
定义使用一系列宏 _IOW/_IOR 等,它们将您的参数类型名称作为参考,以及一个幻数和序数值,这些数值和序数值被修改为您的 ioctl 参数值(例如HIDIOCGRAWINFO
)。类型名称用于编码sizeof(arg_type)
进入定义。这意味着使用的类型user空间决定了value由产生的ioctl
宏 - 即 HIDIOCGRAWINFO 可能会根据包含条件而有所不同。
这是 32 位和 64 位的第一点不同,sizeof
可能会有所不同,具体取决于包装、模糊数据大小(例如长)的使用,但特别是(并且不可避免地)如果您使用指针参数。因此,在这种情况下,想要支持 32 位客户端的 64 位内核模块需要定义一个兼容性参数类型,以匹配参数类型的 32 位等效项的布局,从而匹配 32 位兼容的 ioctl。这些 32 位等效定义利用了称为compat
.
在你的情况下sizeof()
是一样的,所以这不是你正在走的路——但了解可能发生的全部事情很重要。
此外,内核配置可以定义CONFIG_COMPAT
它改变了系统调用包装器(特别是围绕用户/内核接口的代码)ioctl
)以减轻支持 32 位和 64 位的负担。其中一部分包括兼容性ioctl
回调被调用ioctl_compat
.
我所看到的是CONFIG_COMPAT
定义 32 位程序将生成提供以下功能的代码ioctl
到ioctl_compat
回调,即使它could生成相同的ioctl
值与 64 位相同(例如,在您的情况下)。所以驱动程序编写者需要确保ioctl_compat
把手both特殊(不同)32位兼容ioctl
TYPE 和普通的“64 位 - 或未更改的 32 位”类型。
因此,在仅 32 位和仅 64 位系统(无 CONFIG_COMPAT)上设计和测试的内核模块可能适用于 32 位和 64 位程序,但不适用于同时支持两者的程序。
所以在 HID 中我发现这是在 2.6.38 中添加的:
http://lxr.linux.no/#linux+v2.6.38/drivers/hid/hidraw.c#L347 http://lxr.linux.no/#linux+v2.6.38/drivers/hid/hidraw.c#L347