What's different between compiling in 32bit mode and 64bit mode on 64bit os about execution of ioctl function?

自作多情 提交于 2019-12-23 20:26:08

问题


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);
...

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

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

what's the problem?

Note:

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

回答1:


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

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.

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.

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.

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.

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.

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.

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




回答2:


The problem is probably a mismatch between the devinfo structure your program passes to the ioctl function.

I guess your work on a 64 bit system. Thus, your kernel runs in 64 bits, and the kernel module you are talking to (with ioctl) is also 64 bits.

When you compile your user program in 64 bits, the devinfo definition in the kernel module and in the user program is the same.

When you compile your user program in 32 bits, the devinfo definition in the kernel module differs from its definition in your user program. Indeed, in 32 bits, the size of some types changes: mainly long and pointers. Thus, your program create a structure of a certain size, and the kernel module interprets the data it receives differently. The kernel module probably don't understand the value you give to it because it does not look for it at the position you placed it.

The solution is to pay attention to the definition of the devinfo structure so that it has the same binary representation when compiling for 32 bits and for 64 bits.



来源:https://stackoverflow.com/questions/9258280/whats-different-between-compiling-in-32bit-mode-and-64bit-mode-on-64bit-os-abou

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!