Linux カーネル モジュール内のファイルの読み取り/書き込み

可能であれば、Linux カーネル内からのファイル I/O を避ける必要があることに注意してください。主なアイデアは、「1 レベル深く」進み、syscall ハンドラーを直接呼び出す代わりに、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;
}

ファイルを閉じます (close と同様):

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

ファイルからのデータの読み取り (読み取りと同様):

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_read そして vfs_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 でダンスなし) ).