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

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

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值