如何在Linux内核模块中读取/写入文件? [英] How to read/write files within a Linux kernel module?
问题描述
驱动我坚果 - 你永远不应该在内核。然而,问题是2.6.30不导出
sys_read()
。相反,它包裹在 SYSCALL_DEFINE3
中。所以,如果我在我的模块中使用它,我得到以下警告:$ p $
警告:sys_read[xxx.ko] undefined!
警告:sys_open[xxx.ko] undefined!
显然 insmod
无法加载模块,因为链接 b
$ b
问题:
< 2.6.22之后的内核(其中 sys_read()
/ sys_open()
不会被导出)? b $ b
SYSCALL_DEFINEn()
中的系统调用?你应该知道,你应该尽可能地避免文件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); (IS_ERR(filp)){
err = PTR_ERR(filp);
if
返回NULL;
}
return filp;
$ / code>
关闭一个文件(类似于关闭):
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(文件,数据,大小和偏移量);
set_fs(oldfs);
return ret;将数据写入文件(类似于pwrite):
$ b
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(文件,数据,大小和偏移);
set_fs(oldfs);
return ret;
$ / code>
同步更改文件(类似于fsync):
int file_sync(结构文件*文件)
{
vfs_fsync(file,0);
返回0;
原本我建议使用file_fsync,版本。感谢那个可怜的人提出这个改变,但是他的改变被拒绝了。编辑被拒绝之前,我可以检讨它。
I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read
Driving Me Nuts - Things You Never Should Do in the Kernel.
However, problem is 2.6.30 does not export sys_read()
. Rather its wrapped in SYSCALL_DEFINE3
. So if I use that in my module, I get following warnings:
WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
Obviously insmod
cannot load the module because linking does not happen correctly.
Questions:
- How to read/write within kernel after 2.6.22 (where
sys_read()
/sys_open()
are not exported)?
- In general, how to use system calls wrapped in macro
SYSCALL_DEFINEn()
from within the kernel?
解决方案 You should be aware that that you should avoid file I/O when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:
Includes:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
Opening a file (similar to open):
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 a file (similar to close):
void file_close(struct file *file)
{
filp_close(file, NULL);
}
Reading data from a file (similar to 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;
}
Writing data to a file (similar to 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;
}
Syncing changes a file (similar to fsync):
int file_sync(struct file *file)
{
vfs_fsync(file, 0);
return 0;
}
[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.
这篇关于如何在Linux内核模块中读取/写入文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!