カーネルからファイルを読み書きしない理由についてのすべての議論を知っている、代わりに/ procまたはnetlinkを実行します。とにかく読み書きをしたいです。 Driving Me Nuts-カーネルで絶対にすべきでないこと も読みました。
ただし、問題は2.6.30がsys_read()
をエクスポートしないことです。むしろ、_SYSCALL_DEFINE3
_でラップされています。モジュールで使用すると、次の警告が表示されます。
_WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
_
リンクが正しく行われないため、明らかにinsmod
はモジュールをロードできません。
質問:
sys_read()
/sys_open()
はエクスポートされません)SYSCALL_DEFINEn()
にラップされたシステムコールを使用する方法は?可能であれば、ファイル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;
}
ファイルを閉じます(閉じるのと同様):
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_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
)。