linux – 在64位操作系统上编译32位模式和64位操作系统有关ioctl函数的执行有什么不同?

我有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

上一篇:NUC980的GPIO驱动程序


下一篇:Linux音频编程(二)声卡介绍