内核新的ioctl方式--unlocked_ioctl和compat_ioctl(解决error:unknown field 'ioctl' specified in initializer)

来源:互联网 发布:淘宝好评80字以上 编辑:程序博客网 时间:2024/05/16 06:20
CSDN GitHub 内核新的ioctl方式–unlocked_ioctl和compat_ioctl
解决error:unknown field ‘ioctl’ specified in initializer LDD/problem/port/ioctl


知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作


1 问题


把早期 2.6.32之前的驱动移植到新的内核中, 如果驱动中定义了 ioctl 接口, 老是会提示如下错误

error:unknown field ‘ioctl’ specified in initializer

2 原因


单从字面上看, 可以看出是目前我们驱动中定义的 ioctl 接口与内核中 file_operations 结构 ioctl 函数的定义接口不同.

那么内核到底中到底经历了什么呢?

去查看 file_operations 结构体的定义, 可以发现原因是 :

2.6.36 内核上 file_operations 发生了重大的改变 :

原先的, 参见include/linux/fs.h, version 2.6.17, line 1015

int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);

被改为了, 参见include/linux/fs.h, version 4.11, line 1654,

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

具体 file_operations 的实现可以参见include/linux/fs.h, version 4.11, line 1654,

邮件列表参见The new way of ioctl()

早期为了保证兼容性, file_operations 结构体中仍然包含 ioctl 函数指针成员, 但是在 kernel 3.0 中已经完全删除了 struct file_operations 中的 ioctl 函数指针

3 解决方案


因而在实际驱动中, 我们需要

  • 将原先的写的 ioctl 函数声明给改成下面的 unlocked_ioctl 或者 compat_ioctl,

  • file_operations 结构体的初始化中也是一样. 修改为unlocked_ioctl 或者 compat_ioctl,

  • 注意参数的兼容性问题, 新的ioctl() 接口没有 struct inode* 参数, 如果ioctl 接口中使用了 inode, 因此需要通过其他方式获取 inode

内核提供了接口 file_inode 来通过文件指针 file 来获取其 inode 信息, 该函数定义在include/linux/fs.h, version 4.11, line 1213, 如下所示

static inline struct inode *file_inode(const struct file *f){    return f->f_inode;}

因此解决方案如下 :

  1. 首先是将 ioctl 的实现转换为 unlock_ioctl
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)static int XXX_ioctl(        struct inode *indoe,        struct file *filp,        unsigned int cmd,        unsigned long arg){#else//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);//long (*compat_ioctl) (struct file *, unsigned int cmd, unsigned long arg)static long XXX_unlocked_ioctl(        struct file *filp,        unsigned int cmd,        unsigned long arg){    //struct inode *inode = filp->f_dentry->d_inode;    //struct inode *inode = filp->d_inode;    struct inode *inode = inode = file_inode(filp);#endif    /*  此处是ioctl() 函数结构的具体实现  */}

file_operations 结构体初始化的过程采取同样的操作

static struct file_operations fpga_fops = {    .owner  = THIS_MODULE,    .open   = fpga_open,    .read   = fpga_read,    .write = fpga_write,    .llseek = fpga_llseek,#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)    .ioctl = XXX_ioctl,#else    .unlocked_ioctl = XXX_unlocked_ioctl,#endif};

4 参照


ioctl 变成了 unlocked_ioctl

Linux字符设备驱动入门(二)——加入ioctl功能

内核新的ioctl方式—- unlocked_ioctl和compat_ioctl

error: unknown field ‘ioctl’ specified in initializer

error: unknown field ‘ioctl’ specified in initializer

error: unknown field ‘ioctl’ specified in initializer

error:unknown field ‘ioctl’ specified in initializer

error: unknown field ‘ioctl’ specified in initializer

error: unknown field ‘ioctl’ specified in initializer问题


知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作.

0 0
原创粉丝点击