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

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 国际许可协议进行许可, 转载请注明出处, 谢谢合作.

发布了440 篇原创文章 · 获赞 1321 · 访问量 572万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览