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, the problem is that 2.6.30 does not export sys_read()
. Rather it's wrapped in SYSCALL_DEFINE3
. So if I use it in my module, I get the 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:
sys_read()
/sys_open()
are not exported)?SYSCALL_DEFINEn()
from within the kernel?Instead, functions exclusively for kernel's file access are provided: # 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.
If you cannot open your KERNEL file correctly, try to right-click or long-press the file. Then click "Open with" and choose an application.
The Linux® kernel is the main component of a Linux operating system (OS) and is the core interface between a computer's hardware and its processes. It communicates between the 2, managing resources as efficiently as possible.
You should be aware that you should avoid file I/O from within Linux kernel 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With