How to Read/Write From/To a Linux /Proc File from Kernel Space

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



Leave a reply



Submit