您的位置:首页 > 运维架构 > Linux

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

2017-05-08 23:19 1536 查看
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;
}


因此解决方案如下 :

首先是将
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 国际许可协议进行许可, 转载请注明出处, 谢谢合作.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息