113

カーネルからファイルを読み書きするべきではない理由、代わりに/procまたはnetlinkを使用してそれを行う方法についてのすべての議論を知っています。とにかく読み書きしたい。また、 Driving Me Nuts - Things You Should 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()一般に、カーネル内からマクロにラップされたシステム コールを使用する方法は?
4

2 に答える 2

137

可能であれば、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 を使用することを提案しました。変更を提案した貧しい人に感謝しますが、その変更は拒否されました。レビューする前に編集が却下されました。

于 2009-07-26T11:31:03.863 に答える
41

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)。

于 2018-12-24T20:54:44.110 に答える