ioctl命令从32位用户代码在64位系统中错误

我正在将设备驱动程序从32位RHEL 2.6.32升级到64位RHEL 2.6.33.9。

我有一个使用ioctl与该驱动程序交谈的程序。 当驱动程序和程序都是64位或32位时,它可以很好地工作。 但是,当驱动程序是64位,而我的程序是32位时,驱动程序接收到的ioctl命令(在compat_ioctl中)与_IOR和_IOWmacros定义的值不匹配。

在我的驱动程序switch语句中,默认情况下打印出所有有效命令的值,即1-12。 32位ioctl命令远不及那些值。

有人能告诉我什么会导致来自一个32位用户程序的命令在64位驱动程序接收时被搞砸了吗?

这里有一些代码:我必须input它; 该代码是在没有互联网访问的安全系统上,所以请原谅任何错误。 它实际上是确认和运行!

// IOCTL commands from the include file - most omitted // ... #define PORTIO_GET_IRQ_CNT_CMD 10 #define PORTIO_CLR_IRQ_CNT_CMD 11 #define PORTIO_GET_IRQ_TIME_CMD 12 #define PORTIO_IOCTL 'k' // magic number for ioctl // IOCTL Macros #define PORTIO_GET_IRQ_CNT_IOCTL _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_CNT_CMD, unsigned long) #define PORTIO_CLR_IRQ_CNT_IOCTL _IOR(PORTIO_IOCTL, PORTIO_CLR_IRQ_CNT_CMD, unsigned long) #define PORTIO_GET_IRQ_TIME_IOCTL _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_TIME_CMD, unsigned long) 

这是来自portio.c的兼容32位的IOCTL例程。 我已经证实,这只是当我的程序被编译为32位,而驱动程序是64位被称为。

 static long portio_compat_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { unsigned char cmd_number; int cmd_size=0; //... cmd_number = _IOC_NR( cmd ); cmd_size = _IOC_SIZE( cmd ); printk( KERN_ALERT "Portio Compat IOCTL number,size = %d,%d, cmd_number, cmd_size ); //... Switch statement and cases, based on cmd_number } 

输出如下所示:

Portio Compat IOTCL号码,大小= 224,3157

当然,代码需要1到12的IOCTL数字,大小在4或8左右。当代码和驱动程序都是64位或32位时,这就是回来的代码。

在我看来,你的函数compat_ioctl需要太多的参数。 查看Linux内核中的其他定义:

 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 

http://lxr.linux.no/#linux+v3.5.3/block/compat_ioctl.c#L654

 #define PORTIO_GET_IRQ_CNT_IOCTL _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_CNT_CMD, unsigned long) #define PORTIO_CLR_IRQ_CNT_IOCTL _IOR(PORTIO_IOCTL, PORTIO_CLR_IRQ_CNT_CMD, unsigned long) #define PORTIO_GET_IRQ_TIME_IOCTL _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_TIME_CMD, unsigned long) 

将unsigned long更改为unit64_t(固定数据类型) 从ioctl宏参数中移除所有指针,具有:

 .compat_ioctl .unlocked_ioctl in kernel pointing to same function.