error: unknown field 'ioctl' specified in initializer

暑假学嵌入式,在学linux内核驱动的时候,动手写了一个很简单的驱动,遇到了这么一个问题:

error: unknown field ‘ioctl’ specified in initializer。

我原先的代码关键部分先贴出来:

static int hello_ioctl (struct inode inode, struct file filp, unsigned int cmd, unsigned long arg)
{
int ret=0;

switch (cmd) {
case HELLO_ONE:
printk (“HELLO_ONE cmd calledn”);
break;
case HELLO_TWO:
printk (“HELLO_TWO cmd calledn”);
break;
default:
printk (“cmd other calledn”);
break;
}

return ret;
}

struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
.ioctl = hello_ioctl
};

出错提示是.ioctl=hello_ioctl这一句出错了,错误提示的意思是struct file_operations结构体中没有定义ioctl这个red属性。这就让我纳闷了,书上明明说了有的,而且演示代码也是这么写的,怎么到了我这里就不行了呢?

逐一排查错误,最后发现,是内核版本的差异导致的。linux下可以使用命令:uname -r来查看现在正在运行的linux内核版本呢。
书上用的linux内核版本是2.6.26.2,而我的linux版本是3.5.0。在网上查了资料,才知道linux自从2.6.38之后,对struct file_operations结构体做了一些改动,其中就把原来的ioctl属性改为了unlocked_ioctl,函数原型为:long (unlocked_ioctl) (struct file , unsigned int, unsigned long);
这就解释了为什么有那个错误提示了。

了解了出错原因,那修改起来就简单了。如果你的内核版本是2.6.38以下,那不用修改,也不可能会出这个错误,如果内核版本在2.6.38以上,那么做如下修改(以我上面贴出的代码为例):

static int hello_ioctl (struct inode inode, struct file filp, unsigned int cmd, unsigned long arg)
static long hello_ioctl (struct inode inode, struct file filp, unsigned int cmd, unsigned long arg)
{
int ret=0;

switch (cmd) {
case HELLO_ONE:
printk (“HELLO_ONE cmd calledn”);
break;
case HELLO_TWO:
printk (“HELLO_TWO cmd calledn”);
break;
default:
printk (“cmd other calledn”);
break;
}

return ret;
}

struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
.ioctl = hello_ioctl
.unlocked_ioctl = hello_ioctl,
};

上面修改后的部分中,将hello_ioctl函数的返回值改为long,将函数第一个参数inode指针删除掉,将file_operations结构体中的.ioctl属性改为.unlocked_ioctl,然后再编译…..就可以了!

如果还有不明白的,可以发邮件联系我:xinspace@yeah.net