Suppose I have defined the following.
#define MY_IOCTL_CMD1 _IOR(MAGIC_NUMBER, 0x01, arg1)
#define MY_IOCTL_CMD2 _IOW(MAGIC_NUMBER, 0x02, arg2)
#ifdef CONFIG_COMPAT
#define MY_COMPAT_IOCTL_CMD1 _IOR(MAGIC_NUMBER, 0x01, compat_arg1)
#define MY_COMPAT_IOCTL_CMD2 _IOW(MAGIC_NUMBER, 0x02, 开发者_JAVA技巧compat_arg2)
#endif
Now when we do ioctl from user space, we usually do
ioctl(fd, MY_IOCTL_CMD1, &arg1)
Q: Do we really need to have an ioctl with MY_COMPAT_IOCTL_CMD1
as request?
In the devide code I have handlers defined as follows. ioctl: device_ioctl
#ifdef CONFIG_COMPAT
compat_ioctl: device_compat_ioctl
#endif
Can anybody please provide some explanations around this?
This compat stuff is for running a 32-bit program in a 64-bit kernel. When you call the ioctl(fd, MY_IOCTL_CMD1, &arg1)
from a 32-bit program on a 64-bit kernel, the kernel will divert the ioctl to the .compat_ioctl
function in the file_operations
struct. This compat_ioctl
function is responsible for copying the user argument arg1
as if it were compat_arg1
, which uses the 32-bit layout. The compat_arg1
typedef is defined in the kernel so that when compiled for 64-bit, the structure is exactly the same layout as the arg1
compiled for 32-bit.
The definition of MY_IOCTL_CMD1
will take the sizeof arg1
into account when creating the cmd id. When you compile a program for a 32-bit machine, the value for MY_IOCTL_CMD1
will be different than if you compiled it for a 64-bit machine. The 32-bit MY_IOCTL_CMD1
should have the same value as the 64-bit MY_COMPAT_IOCTL_CMD1
in the kernel, however.
There's never a need to use compat_arg1
or MY_COMPAT_IOCTL_CMD1
in a user-space application. Those are only for code compiled in the kernel.
精彩评论