Sophie

Sophie

distrib > Mageia > 7 > armv7hl > by-pkgid > 265a7483afc48e27c236b36e810be507 > files > 102

lkmpg-1.1.0-23.mga7.noarch.rpm

<HTML
><HEAD
><TITLE
>The /proc File System</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="The Linux Kernel Module Programming Guide"
HREF="book1.htm"><LINK
REL="PREVIOUS"
TITLE="Character Device Files"
HREF="c606.htm"><LINK
REL="NEXT"
TITLE="Using /proc For Input"
HREF="c792.htm"></HEAD
><BODY
CLASS="CHAPTER"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>The Linux Kernel Module Programming Guide</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="c606.htm"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="c792.htm"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="CHAPTER"
><H1
><A
NAME="AEN745"
></A
>Chapter 5. The /proc File System</H1
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="AEN747"
></A
>The /proc File System</H1
><A
NAME="AEN749"
></A
><A
NAME="AEN752"
></A
><P
>In Linux there is an additional mechanism for the kernel and kernel modules to send information to processes --- the
	<TT
CLASS="FILENAME"
>/proc</TT
> 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
	<TT
CLASS="FILENAME"
>/proc/modules</TT
> which has the list of modules and <TT
CLASS="FILENAME"
>/proc/meminfo</TT
> which has memory usage
	statistics.</P
><A
NAME="AEN760"
></A
><A
NAME="AEN763"
></A
><P
>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 <TT
CLASS="FILENAME"
>/proc</TT
> file, including pointers to any handler
	functions (in our case there is only one, the one called when somebody attempts to read from the <TT
CLASS="FILENAME"
>/proc</TT
> file). Then, <TT
CLASS="FUNCTION"
>init_module</TT
> registers the structure with the kernel and
	<TT
CLASS="FUNCTION"
>cleanup_module</TT
> unregisters it.</P
><P
>The reason we use <TT
CLASS="FUNCTION"
>proc_register_dynamic</TT
><A
NAME="AEN773"
HREF="#FTN.AEN773"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
> is because we don't want to determine the inode number
	used for our file in advance, but to allow the kernel to determine it to prevent clashes. Normal file systems are located on a
	disk, rather than just in memory (which is where <TT
CLASS="FILENAME"
>/proc</TT
> is), and in that case the inode
	number is a pointer to a disk location where the file's index-node (inode for short) is located. The inode contains
	information about the file, for example the file's permissions, together with a pointer to the disk location or locations
	where the file's data can be found.</P
><A
NAME="AEN776"
></A
><A
NAME="AEN779"
></A
><A
NAME="AEN782"
></A
><P
>Because we don't get called when the file is opened or closed, there's no where for us to put
	<TT
CLASS="VARNAME"
>try_module_get</TT
> and <TT
CLASS="VARNAME"
>try_module_put</TT
> 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 <TT
CLASS="FILENAME"
>/proc</TT
> files which will allow us to protect against
	this problem as well.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN788"
></A
><P
><B
>Example 5-1. procfs.c</B
></P
><PRE
CLASS="PROGRAMLISTING"
>/*
 *  procfs.c -  create a "file" in /proc
 */

#include &#60;linux/module.h&#62;	/* Specifically, a module */
#include &#60;linux/kernel.h&#62;	/* We're doing kernel work */
#include &#60;linux/proc_fs.h&#62;	/* Necessary because we use the proc fs */

struct proc_dir_entry *Our_Proc_File;

/* Put data into the proc fs file.
 * 
 * Arguments
 * =========
 * 1. The buffer where the data is to be inserted, if
 *    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. Write a "1" here to indicate EOF.
 * 6. A pointer to data (useful in case one common 
 *    read for multiple /proc/... entries)
 *
 * Usage and Return Value
 * ======================
 * 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 &#60;kernel source
 * directory&#62;/fs/proc/array.c.
 *
 * 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.
 */
ssize_t
procfile_read(char *buffer,
	      char **buffer_location,
	      off_t offset, int buffer_length, int *eof, void *data)
{
	printk(KERN_INFO "inside /proc/test : procfile_read\n");

	int len = 0;		/* The number of bytes actually used */
	static int count = 1;

	/* 
	 * We give all of our information in one go, so if the
	 * 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 &#62; 0) {
		printk(KERN_INFO "offset %d : /proc/test : procfile_read, \
		       wrote %d Bytes\n", (int)(offset), len);
		*eof = 1;
		return len;
	}

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

	/* 
	 * Return the length 
	 */
	printk(KERN_INFO
	       "leaving /proc/test : procfile_read, wrote %d Bytes\n", len);
	return len;
}

int init_module()
{
	int rv = 0;
	Our_Proc_File = create_proc_entry("test", 0644, NULL);
	Our_Proc_File-&#62;read_proc = procfile_read;
	Our_Proc_File-&#62;owner = THIS_MODULE;
	Our_Proc_File-&#62;mode = S_IFREG | S_IRUGO;
	Our_Proc_File-&#62;uid = 0;
	Our_Proc_File-&#62;gid = 0;
	Our_Proc_File-&#62;size = 37;

	printk(KERN_INFO "Trying to create /proc/test:\n");

	if (Our_Proc_File == NULL) {
		rv = -ENOMEM;
		remove_proc_entry("test", &#38;proc_root);
		printk(KERN_INFO "Error: Could not initialize /proc/test\n");
	} else {
		printk(KERN_INFO "Success!\n");
	}

	return rv;
}

void cleanup_module()
{
	remove_proc_entry("test", &#38;proc_root);
	printk(KERN_INFO "/proc/test removed\n");
}</PRE
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN773"
HREF="c745.htm#AEN773"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>In version 2.0, in version 2.2 this is done
	for us automatically if we set the inode to zero.</P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="c606.htm"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.htm"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="c792.htm"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Character Device Files</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Using /proc For Input</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>