如何在Linux内核模块中读取/写入文件? [英] How to read/write files within a Linux kernel module?

查看:229
本文介绍了如何在Linux内核模块中读取/写入文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道所有关于为什么不应该从内核读取/写入文件的讨论,而是如何使用/ proc或netlink来做到这一点。无论如何,我想读/写。我还读了
驱动我坚果 - 你永远不应该在内核。然而,问题是2.6.30不导出 sys_read()。相反,它包裹在 SYSCALL_DEFINE3 中。所以,如果我在我的模块中使用它,我得到以下警告:

$ p $ 警告:sys_read[xxx.ko] undefined!
警告:sys_open[xxx.ko] undefined!

显然 insmod 无法加载模块,因为链接 b
$ b

问题:

< 2.6.22之后的内核(其中 sys_read() / sys_open()不会被导出)? b $ b

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


  • 解决方案

    你应该知道,你应该尽可能地避免文件I / O。主要思路是深入一层,并调用 VFS级别函数而不是系统调用包括:

      #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); (IS_ERR(filp)){
    err = PTR_ERR(filp);
    if
    返回NULL;
    }
    return filp;

    $ / code>

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

      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(文件,数据,大小和偏移量);

    set_fs(oldfs);
    return ret;将数据写入文件(类似于pwrite):





    $ b



      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(文件,数据,大小和偏移);

    set_fs(oldfs);
    return ret;

    $ / code>

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

      int file_sync(结构文件*文件)
    {
    vfs_fsync(file,0);
    返回0;





    原本我建议使用file_fsync,版本。感谢那个可怜的人提出这个改变,但是他的改变被拒绝了。编辑被拒绝之前,我可以检讨它。


    I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read Driving Me Nuts - Things You Never Should Do in the Kernel.

    However, problem is 2.6.30 does not export sys_read(). Rather its wrapped in SYSCALL_DEFINE3. So if I use that in my module, I get following warnings:

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

    Obviously insmod cannot load the module because linking does not happen correctly.

    Questions:

    • How to read/write within kernel after 2.6.22 (where sys_read()/sys_open() are not exported)?
    • In general, how to use system calls wrapped in macro SYSCALL_DEFINEn() from within the kernel?

    解决方案

    You should be aware that that you should avoid file I/O when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:

    Includes:

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

    Opening a file (similar to open):

    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;
    }
    

    Close a file (similar to close):

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

    Reading data from a file (similar to 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;
    }   
    

    Writing data to a file (similar to 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;
    }
    

    Syncing changes a file (similar to fsync):

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

    [Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.

    这篇关于如何在Linux内核模块中读取/写入文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆