在ibitl函数的执行上,在64位操作系统上以32位模式和64位模式进行编译有什么区别?

在ibitl函数的执行上,在64位操作系统上以32位模式和64位模式进行编译有什么区别?

问题描述:

我有一个64位的Enterprice SuSE 11 我有一个打开HIDRAW设备并在其上操作ioctl函数以从该设备获取原始信息的应用程序,如下所示:

I have a 64 bit Enterprice SuSE 11 I have an application which open a HIDRAW device and operate an ioctl function on it to get raw info from this device like below:

struct hidraw_devinfo devinfo;
int fd = open("/dev/hidraw0", 0);
int ret = ioctl(fd, HIDIOCGRAWINFO, &devinfo);
...

如果我以64位模式编译该程序,则没有错误,也没有问题,当我执行该应用程序时,ioctl函数可以正常工作.

If I compile this program in 64 bit mode there is no error and no problem and when I execute the application the ioctl function works properly.

g++ main.cpp

如果我以32位模式编译该程序,那么也没有错误,也没有问题.但是当我执行应用程序时,ioctl函数返回EINVAL错误(errno = 22,无效参数)

If I complie this program in 32 bit mode there is also no error and no problem. but when I execute the application the ioctl function return EINVAL error(errno = 22 , Invalid Argument)

g++ -m32 main.cpp

出什么问题了?

注意:

struct hidraw_devinfo 
{
     __u32 bustype;
     __s16 vendor;
     __s16 product;
}

Linux ioctl定义和兼容性层是一个令人着迷的有趣话题,

Linux ioctl definitions and compatibility layers are a fascinating topic I've just bashed my head against.

通常ioctl定义使用_IOW/_IOR等宏家族,这些宏以您的参数类型名作为参考,以及一个魔术数字和序数值,这些值被修剪以赋予您ioctl参数值(例如HIDIOCGRAWINFO).类型名称用于将sizeof(arg_type)编码为定义.这意味着 user 空间中使用的类型决定了ioctl宏生成的 value -即HIDIOCGRAWINFO可能会根据包含条件而有所不同.

Typically ioctl definitions use a family of macros _IOW/_IOR et al that take your argument type-name as a reference, along with a magic number and ordinal value that are munged to give you your ioctl argument value (eg HIDIOCGRAWINFO). The type-name is used to encode sizeof(arg_type) into the definition. This means that the type used in user space determines the value generated by the ioctl macro - ie HIDIOCGRAWINFO may vary based on include conditions.

这是32位和64位不同的第一点,sizeof可能有所不同,具体取决于打包,使用模糊的数据大小(例如,长),但如果使用指针,则尤其(不可避免)争论.因此,在这种情况下,想要支持32位客户端的64位内核模块确实定义了兼容性参数类型,以匹配参数类型的等效32位布局,从而匹配32位兼容ioctl.这些等效的32位定义使用称为compat的内核工具/层.

Here is the first point where 32- and 64-bit differ, the sizeof may differ, depending on packing, use of vague data-sizes (eg long), but especially (and unavoidably) if you use a pointer argument. So in this case a 64-bit kernel module what wants to support 32-bit clients needs do define a compatibility argument-type to match the layout of the 32-bit equivalent of the argument type and thus a 32-bit compatible ioctl. These 32-bit equivalent definitions make use of a kernel facility/layer called compat.

在您的情况下,sizeof()是相同的,所以这不是您要走的路-但了解所有可能发生的事情很重要.

In your case the sizeof() is the same so that is not the path you are taking - but its important to understand the whole of what could be happening.

此外,内核配置可以定义CONFIG_COMPAT,它可以更改系统调用包装程序(特别是围绕用户/内核接口wrt ioctl的代码),以减轻支持32位和64位的负担.其中的一部分包括称为ioctl_compat的兼容性ioctl回调.

In addition a kernel configuration may define CONFIG_COMPAT which changes the sys-call wrappers (especially the code surrounding the user/kernel interface wrt ioctl) to ease the burden of supporting 32- and 64-bit. Part of this includes a compatibility ioctl callback called ioctl_compat.

我所看到的是CONFIG_COMPAT定义的,即32位程序将生成将ioctl传递给ioctl_compat回调的代码,即使它可以生成相同的ioctl value就像64位一样(例如您的情况).因此,驱动程序编写者需要确保ioctl_compat处理两者都是特殊的(不同的)32位兼容的ioctl TYPE和普通的"64位-或不变的32位"类型.

What I've seen is with CONFIG_COMPAT defined that 32-bit programs will generate code that delivers ioctls to the ioctl_compat callback, even if it could generate the same ioctl value as 64-bit does (eg in your case). So the driver writer needs to make sure that ioctl_compat handles both the special (different) 32-bit compatible ioctl TYPEs and the normal "64-bit - or unchanged 32-bit" types.

因此,在仅32位和仅64位系统(没有CONFIG_COMPAT)上设计和测试的内核模块可能适用于32位和64位程序,但不适用于同时支持两者的程序.

So a kernel-module designed and tested on 32-bit only and 64-bit only systems (without CONFIG_COMPAT) may work for 32- and 64-bit programs, but not for one which supports both.

因此,在HID中,我看到它是在2.6.38中添加的:

So looking in HID I see this was added in 2.6.38:

http://lxr.linux.no /#linux+v2.6.38/drivers/hid/hidraw.c#L347