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;
}
因此解决方案如下 :
- 首先是将
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和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 国际许可协议进行许可, 转载请注明出处, 谢谢合作.