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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章