簡體   English   中英

在 Linux 內核模塊中讀/寫文件

[英]Read/write files within a Linux kernel module

我知道所有關於為什么不應該從內核讀/寫文件,而是如何使用/procnetlink來做到這一點的討論。 無論如何我都想讀/寫。 我還閱讀了讓我發瘋——你永遠不應該在內核中做的事情

但是,問題是 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()系統調用?

您應該意識到應該盡可能避免在 Linux 內核中進行文件 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);
    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,它在較新的內核版本中消失了。 感謝那個可憐的家伙建議改變,但他的改變被拒絕了。 在我審核之前,編輯被拒絕了。

從 Linux 內核 4.14 版開始,不再導出vfs_readvfs_write函數以用於模塊。 相反,提供了專門用於內核文件訪問的函數:

# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);

# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
            loff_t *pos);

此外, filp_open不再接受用戶空間的字符串,因此它可以(與不跳舞用於內核直接訪問set_fs )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM