我知道所有关于为什么不应该从内核读取/写入文件的讨论,而是如何使用 / proc 或 netlink 来做到这一点。无论如何我想读/写。我也读过 Driving Me Nuts - Things You 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
无法加载模块,因为链接没有正确发生。
问题:
sys_read()
/ sys_open()
未导出)?SYSCALL_DEFINEn()
中包含的系统调用?答案 0 :(得分:107)
您应该知道,应尽可能避免文件I / O.主要思想是“更深层次”并直接调用VFS level functions而不是syscall处理程序:
包括:
#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,它在较新的内核版本中消失了。感谢可怜的家伙提出改变,但他的改变被拒绝了。在我审核之前,编辑被拒绝了。
答案 1 :(得分:7)
自Linux内核4.14版以来,{strong>不再导出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
共舞)。