我正在将设备驱动程序从 32 位 RHEL 2.6.32 升级到 64 位 RHEL 2.6.33.9。
我有一个使用 ioctl 与该驱动程序对话的程序。当驱动程序和程序都是 64 位或 32 位时,它可以完美运行。但是当驱动是 64 位,而我的程序是 32 位时,驱动接收到的 ioctl 命令(在 compat_ioctl 中)与 _IOR 和 _IOW 宏定义的值不匹配。
在我的驱动程序的 switch 语句中,默认情况下打印出所有有效命令的值,即 1-12。32 位 ioctl 命令与这些值相去甚远。
有人能告诉我在 64 位驱动程序中收到来自 32 位用户程序的命令时,什么会导致混乱?
这是一些代码:我必须输入它;该代码位于无法访问互联网的安全系统上,因此请原谅任何拼写错误。它确实会跑来跑去!
// 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 位时返回的结果。