LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (http://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   Where does the actual write happens when writing to a proc file? (http://www.linuxquestions.org/questions/linux-kernel-70/where-does-the-actual-write-happens-when-writing-to-a-proc-file-845236/)

archieval 11-19-2010 12:59 AM

Where does the actual write happens when writing to a proc file?
 
Hi everyone,

I wanted to create a proc file in my driver which will be updated every time a certain event happens. I have read about this http://linux.die.net/lkmpg/x769.html

Here is the code in that site:

Code:

/**
 *  procfs2.c -  create a "file" in /proc
 *
 */

#include <linux/module.h>        /* Specifically, a module */
#include <linux/kernel.h>        /* We're doing kernel work */
#include <linux/proc_fs.h>        /* Necessary because we use the proc fs */
#include <asm/uaccess.h>        /* for copy_from_user */

#define PROCFS_MAX_SIZE                1024
#define PROCFS_NAME                "buffer1k"

/**
 * This structure hold information about the /proc file
 *
 */
static struct proc_dir_entry *Our_Proc_File;

/**
 * The buffer used to store character for this module
 *
 */
static char procfs_buffer[PROCFS_MAX_SIZE];

/**
 * The size of the buffer
 *
 */
static unsigned long procfs_buffer_size = 0;

/**
 * This function is called then the /proc file is read
 *
 */
int
procfile_read(char *buffer,
              char **buffer_location,
              off_t offset, int buffer_length, int *eof, void *data)
{
        int ret;
       
        printk(KERN_INFO "procfile_read (/proc/%s) called\n", PROCFS_NAME);
       
        if (offset > 0) {
                /* we have finished to read, return 0 */
                ret  = 0;
        } else {
                /* fill the buffer, return the buffer size */
                memcpy(buffer, procfs_buffer, procfs_buffer_size);
                ret = procfs_buffer_size;
        }

        return ret;
}

/**
 * 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;
}

/**
 *This function is called when the module is loaded
 *
 */
int init_module()
{
        /* create the /proc file */
        Our_Proc_File = create_proc_entry(PROCFS_NAME, 0644, NULL);
       
        if (Our_Proc_File == NULL) {
                remove_proc_entry(PROCFS_NAME, &proc_root);
                printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
                        PROCFS_NAME);
                return -ENOMEM;
        }

        Our_Proc_File->read_proc  = procfile_read;
        Our_Proc_File->write_proc = procfile_write;
        Our_Proc_File->owner          = THIS_MODULE;
        Our_Proc_File->mode          = S_IFREG | S_IRUGO;
        Our_Proc_File->uid          = 0;
        Our_Proc_File->gid          = 0;
        Our_Proc_File->size          = 37;

        printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME);       
        return 0;        /* everything is ok */
}

/**
 *This function is called when the module is unloaded
 *
 */
void cleanup_module()
{
        remove_proc_entry(PROCFS_NAME, &proc_root);
        printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME);
}


It looks simple but I cannot see the point where the actual write happens. The internal buffer used, procfs_buffer, is where the data from user space buffer is copied. I'm not sure if I am missing anything but procfs_buffer is not used anywhere aside from that. I was expecting a transfer from procfs_buffer to another address probably a member of the proc_dir_entry but there isn't any.

Regards,
archieval

module0000 11-19-2010 08:20 AM

This may be less details than you like..it's a high-level overview of how proc works:

There is no actual file there, or write happening. What that snippet of code does is hook to /proc/<foo>, and whenever a user 'writes'(using echo, a pipe, or some other mechanism), that code executes procfile_write(), which is passed directly what the user wrote. The reverse happens if a user reads(cat, less, etc) that /proc/<foo> entry, the kernel calls procfile_read(), and returns whatever value that function returns.

Hopefully that makes sense...the summary is that there is no actual reading/writing. When you think of the file as being read or written to, it's really the respective read/write function being called and storing/returning a value.

This is very similar to writing a kernel module that utilizes /dev/<foo>, you define a read/write function that corresponds to userspace reading or writing to /dev, and you communicate with userspace using the same method the code snippet above uses.

nini09 11-19-2010 02:58 PM

You need modify procfile_write function to write new value to local variable in driver module after you get new value from user space.

archieval 11-19-2010 07:05 PM

Ok, now I think I get it a bit. The proc file above can only be modified by a user space application. After you create it initially, it has no value, so reading from it, will transfer empty content of procfs_buffer to the user space buffer. When no user space program writes to it, it will never have any value. When a program writes into it, it is stored in procfs_buffer, then will be used when a program reads it. Why the hell am I thinking too complicated when it was actually too simple! So the purpose of this whole code is for storage of data only. I should have gone read the previous topic before that, which changes the content of the proc file internally. And I should have not thought of a proc file as a "regular text file", but something more like a "device" (with the /proc/myfile as device file). And the code above is a device driver that will communicate with the "storage device" to store or read data from it. A "device driver" for no actual device!

So to integrate it to my actual device driver that updates something when an event happens, I would only need the read part since the procfs_buffer will be updated internally.

Thanks everyone!

Regards,
archieval

AwesomeMachine 11-21-2010 11:43 PM

/proc is a virtual filesystem. It's just values within the kernel or links to device files.


All times are GMT -5. The time now is 11:07 AM.