首页 文章

在Linux内核模块中读/写文件

提问于
浏览
79

我知道所有关于为什么不应该从内核读/写文件的讨论,而是如何使用/ proc或netlink来做到这一点 . 无论如何我想读/写 . 我也读过Driving Me Nuts - Things You Never Should Do in the Kernel .

但是,问题是2.6.30不导出 sys_read() . 相反,它包含在 SYSCALL_DEFINE3 中 . 因此,如果我在我的模块中使用它,我会收到以下警告:

WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!

显然 insmod 无法加载模块,因为链接没有正确发生 .

问题:

  • 如何在2.6.22之后在内核中读/写(其中 sys_read() / sys_open() 未导出)?

  • 一般来说,如何在内核中使用包含在宏 SYSCALL_DEFINEn() 中的系统调用?

1 回答

  • 102

    您应该知道,应尽可能避免文件I / O.主要想法是"one level deeper"并直接调用VFS level functions而不是syscall处理程序:

    包括:

    #include <linux/fs.h>
    #include <asm/segment.h>
    #include <asm/uaccess.h>
    #include <linux/buffer_head.h>
    

    打开文件(类似于打开):

    struct file *file_open(const char *path, int flags, int rights) 
    {
        struct file *filp = NULL;
        mm_segment_t oldfs;
        int err = 0;
    
        oldfs = get_fs();
        set_fs(get_ds());
        filp = filp_open(path, flags, rights);
        set_fs(oldfs);
        if (IS_ERR(filp)) {
            err = PTR_ERR(filp);
            return NULL;
        }
        return filp;
    }
    

    关闭文件(类似于关闭):

    void file_close(struct file *file) 
    {
        filp_close(file, NULL);
    }
    

    从文件中读取数据(类似于pread):

    int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
    {
        mm_segment_t oldfs;
        int ret;
    
        oldfs = get_fs();
        set_fs(get_ds());
    
        ret = vfs_read(file, data, size, &offset);
    
        set_fs(oldfs);
        return ret;
    }
    

    将数据写入文件(类似于pwrite):

    int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
    {
        mm_segment_t oldfs;
        int ret;
    
        oldfs = get_fs();
        set_fs(get_ds());
    
        ret = vfs_write(file, data, size, &offset);
    
        set_fs(oldfs);
        return ret;
    }
    

    同步更改文件(类似于fsync):

    int file_sync(struct file *file) 
    {
        vfs_fsync(file, 0);
        return 0;
    }
    

    [编辑]最初,我建议使用file_fsync,它在较新的内核版本中消失了 . 感谢可怜的家伙提出改变,但他的改变被拒绝了 . 在我审核之前,编辑被拒绝了 .

相关问题