5.1. The /proc File System

In Linux there is an additional mechanism for the kernel and kernel modules to send information to processes --- the /proc file system. Originally designed to allow easy access to information about processes (hence the name), it is now used by every bit of the kernel which has something interesting to report, such as /proc/modules which has the list of modules and /proc/meminfo which has memory usage statistics.

The method to use the proc file system is very similar to the one used with device drivers --- you create a structure with all the information needed for the /proc file, including pointers to any handler functions (in our case there is only one, the one called when somebody attempts to read from the /proc file). Then, init_module registers the structure with the kernel and cleanup_module unregisters it.


Because we don't get called when the file is opened or closed, there's no where for us to put MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT in this module, and if the file is opened and then the module is removed, there's no way to avoid the consequences. In the next chapter we'll see a harder to implement, but more flexible, way of dealing with /proc files which will allow us to protect against this problem as well.

Example 5-1. procfs.c

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


#include <linux/modversions.h>

/* Necessary because we use the proc fs */
#include <linux/proc_fs.h>

 * here if necessary. */

/* Put data into the proc fs file.

      you decide to use it.
   2. A pointer to a pointer to characters. This is 
      useful if you don't want to use the buffer 
      allocated by the kernel.
   3. The current position in the file. 
   4. The size of the buffer in the first argument.  
   5. Zero (for future use?).

   Usage and Return Value
   If you use your own buffer, like I do, put its 
   location in the second argument and return the 
   number of bytes used in the buffer.

   A return value of zero means you have no further 
   information at this time (end of file). A negative 
   return value is an error condition.

   For More Information
   The way I discovered what to do with this function 
   wasn't by reading documentation, but by reading the 
   code which used it. I just looked to see what uses 
   the get_info field of proc_dir_entry struct (I used a 
   combination of find and grep, if you're interested), 
   and I saw that  it is used in <kernel source 

   If something is unknown about the kernel, this is 
   usually the way to go. In Linux we have the great 
   advantage of having the kernel source code for 
   free - use it.
int procfile_read(char *buffer, 
		  char **buffer_location, 
		  off_t offset, 
		  int buffer_length, 
		  int zero)

  /* This is static so it will still be in memory 
   * when we leave this function */
  static char my_buffer[80];  

  static int count = 1;

   * user asks us if we have more information the 
   * answer should always be no. 
   * This is important because the standard read 
   * function from the library would continue to issue 
   * the read system call until the kernel replies
   * that it has no more information, or until its 
   * buffer is filled.
  if (offset > 0)
    return 0;

  /* Fill the buffer and get its length */
  len = sprintf(my_buffer, 
    "For the %d%s time, go away!\n", count,
    (count % 100 > 10 && count % 100 < 14) ? "th" : 
      (count % 10 == 1) ? "st" :
        (count % 10 == 2) ? "nd" :
          (count % 10 == 3) ? "rd" : "th" );

  /* Tell the function which called us where the 
   * buffer is */
  *buffer_location = my_buffer;

  /* Return the length */
  return len;

struct proc_dir_entry Our_Proc_File = 
        * proc_register[_dynamic] */
    4, /* Length of the file name */
    "test", /* The file name */
                        * file which can be read by its 
                        * owner, its group, and everybody
                        * else */
    1,	/* Number of links (directories where the 
         * file is referenced) */
            * to root */
    NULL, /* functions which can be done on the inode 
           * (linking, removing, etc.) - we don't 
           * support any. */
    procfile_read, /* The read function for this file, 
                    * the function called when somebody 
                    * tries to read something from it. */
    NULL /* We could have here a function to fill the 
          * file's inode, to enable us to play with 
          * permissions, ownership, etc. */

/* Initialize the module - register the proc file */
int init_module()
  /* Success if proc_register[_dynamic] is a success, 
   * failure otherwise. */
  /* In version 2.2, proc_register assign a dynamic 
   * inode number automatically if it is zero in the 
   * structure , so there's no more need for 
   * proc_register_dynamic
  return proc_register(&proc_root, &Our_Proc_File);
  return proc_register_dynamic(&proc_root, &Our_Proc_File);
  /* proc_root is the root directory for the proc 
   * located. 

/* Cleanup - unregister our file from /proc */
void cleanup_module()
  proc_unregister(&proc_root, Our_Proc_File.low_ino);



In version 2.0, in version 2.2 this is done for us automatically if we set the inode to zero.