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 國際許可協議進行許可, 轉載請註明出處, 謝謝合作.