我有64位Enterprice SuSE 11
我有一个应用程序打开一个HIDRAW设备并在其上运行ioctl功能,以获取此设备的原始信息,如下所示:
struct hidraw_devinfo devinfo;
int fd = open("/dev/hidraw0", 0);
int ret = ioctl(fd, HIDIOCGRAWINFO, &devinfo);
...
如果我在64位模式下编译该程序没有错误也没有问题,当我执行应用程序时,ioctl功能正常工作.
g++ main.cpp
如果我在32位模式下编译该程序,也没有错误也没有问题.但是当我执行应用程序时,ioctl函数返回EINVAL错误(errno = 22,无效参数)
g++ -m32 main.cpp
有什么问题?
注意:
struct hidraw_devinfo
{
__u32 bustype;
__s16 vendor;
__s16 product;
}
解决方法:
Linux ioctl定义和兼容性层是一个引人入胜的话题.
通常,ioctl定义使用一系列宏_IOW / _IOR等,它们将您的参数类型名称作为引用,以及为您提供ioctl参数值(例如HIDIOCGRAWINFO)的幻数和序数值. type-name用于将sizeof(arg_type)编码到定义中.这意味着用户空间中使用的类型决定了ioctl宏生成的值 – 即HIDIOCGRAWINFO可能会根据包含条件而有所不同.
这是32位和64位不同的第一点,sizeof可能会有所不同,具体取决于打包,使用模糊数据大小(例如long),但如果使用指针参数,则尤其(并且不可避免地).因此,在这种情况下,需要支持32位客户端需要的64位内核模块需要定义兼容性参数类型以匹配参数类型的32位等效的布局,从而匹配32位兼容的ioctl.这些32位等效定义使用名为compat的内核工具/层.
在你的情况下,sizeof()是相同的,所以这不是你正在采取的路径 – 但重要的是要了解可能发生的全部事情.
此外,内核配置可以定义CONFIG_COMPAT,它可以更改sys-call包装器(尤其是围绕用户/内核接口的代码),以减轻支持32位和64位的负担.其中一部分包括名为ioctl_compat的兼容性ioctl回调.
我所看到的是,CONFIG_COMPAT定义了32位程序将生成将ioctl传递给ioctl_compat回调的代码,即使它可以生成与64位相同的ioctl值(例如在您的情况下).因此驱动程序编写者需要确保ioctl_compat处理特殊(不同)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