How to read/write from/to a linux /proc file from kernel space?
That's not how it works. When a userspace program opens the files, they are generated on the fly on a case-by-case basis. Most of them are readonly and generated by a common mechanism:
- Register an entry with create_proc_read_entry
- Supply a callback function (called read_proc by convention) which is called when the file is read
- This callback function should populate a supplied buffer and (typically) call proc_calc_metrics to update the file pointer etc supplied to userspace.
You (from the kernel) do not "write" to procfs files, you supply the results dynamically when userspace requests them.
Read/write files within a Linux kernel module
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.
Check /proc file from C kernel module
Source : linux.die.net/lkmpg/x769.html
/**
* This function is called with the /proc file is written
*
*/
int procfile_write(struct file *file, const char *buffer, unsigned long count,
void *data)
{
/* get buffer size */
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
/* write data to the buffer */
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return -EFAULT;
}
return procfs_buffer_size;
}
To clarify, in Your module whenever user writes to Your file in procfs, this example shows how to handle such write.
kernel module: reading existing proc file (proc_create)
I asked this question as I wanted to filter out /proc/pid/maps. It has a large number of entries and impacting the performance of my workload. Thanks to @0andriy and @Tsyvarev for guiding me as a newbie. I have included the code I have to filter and generate modified maps. I have attached code snippet in case it helps a newbie like me in generating their version of /proc/pid/maps.
static int proc_show(struct seq_file *s, void *v) {
struct task_struct *task;
struct pid *pid_struct;
struct mm_struct *mm;
struct vm_area_struct *vma;
unsigned long start, end;
const char *region = NULL;
// Look for task which PID was provided as parameter, falling back to current task if not found
if(pid == 0) {
printk(KERN_INFO "pages_activity: no pid argument provided, using current process instead\n");
task = current;
} else {
pid_struct = find_get_pid(pid);
if(pid_struct == NULL) {
printk(KERN_INFO "pages_activity: process with pid %d not found, using current process instead\n", pid);
task = current;
} else {
task = pid_task(pid_struct, PIDTYPE_PID);
}
}
mm = task->mm;
vma = mm->mmap;
Write to proc in a kernel module which uses also a character device
As Tsyvarev mentioned use different file_operations
static struct proc_dir_entry *procfs;
static const struct file_operations proc_fops = {
.owner = THIS_MODULE,
.open = open_proc_fn,
.read = read_proc_fn,
};
static const struct file_operations char_fops = {
.owner = THIS_MODULE,
.open = open_char_fn,
.read = read_char_fn,
.write = write_char_fn,
};
int __init init_mod (void) {
procfs = proc_create("filename", 0, NULL, &proc_fops);
if(!proc)
return -1;
<Register char device with &char_fops >
return 0;
}
Related Topics
Vimdiff: How to Put All Changes Inside a Particular Function from One File to Another
How to Set Pthread CPU Affinity in Os X
Is Visual Basic Supported by .Net Core on Linux
Dependency Failure While Installing Libboost-All-Dev on Ubuntu Core 14.04
Why Does Wget Output to Stderr Rather Than Stdout
Understanding The Getting of Task_Struct Pointer from Process Kernel Stack
How to Use Performance Counters Inside of The Kernel
X11 Forwarding of Gui App in Docker Container
How Does This Perl One Liner in The Bash Works
Exit from Bash Script But Keep The Process Running
Undefined Reference to Symbol 'Timer_Settime@@Glibc_2.3.3
Interprocess Communication via Pipes
Xargs and Find, Rm Complaining About \N (Newline) in Filename