Sophie

Sophie

distrib > Mandriva > current > i586 > by-pkgid > afdcfc364877ff5b5fc90cad008e9a19 > files > 104

lkmpg-1.1.0-15mdv2010.0.noarch.rpm

<HTML
><HEAD
><TITLE
>Using /proc For Input</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="The /proc File System"
HREF="c745.htm"><LINK
REL="NEXT"
TITLE="Talking To Device Files"
HREF="c883.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="c745.htm"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="c883.htm"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="CHAPTER"
><H1
><A
NAME="AEN792"
></A
>Chapter 6. Using /proc For Input</H1
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="AEN794"
></A
>Using /proc For Input</H1
><A
NAME="AEN796"
></A
><A
NAME="AEN799"
></A
><P
>So far we have two ways to generate output from kernel modules: we can register a device driver and
	<B
CLASS="COMMAND"
>mknod</B
> a device file, or we can create a <TT
CLASS="FILENAME"
>/proc</TT
> file. This allows the
	kernel module to tell us anything it likes. The only problem is that there is no way for us to talk back. The first way we'll
	send input to kernel modules will be by writing back to the <TT
CLASS="FILENAME"
>/proc</TT
> file.</P
><P
>Because the proc filesystem was written mainly to allow the kernel to report its situation to processes, there are no
	special provisions for input.  The <TT
CLASS="VARNAME"
>struct proc_dir_entry</TT
> doesn't include a pointer to an input function,
	the way it includes a pointer to an output function. Instead, to write into a <TT
CLASS="FILENAME"
>/proc</TT
>
	file, we need to use the standard filesystem mechanism.</P
><A
NAME="AEN809"
></A
><P
>In Linux there is a standard mechanism for file system registration. Since every file system has to have its own
	functions to handle inode and file operations<A
NAME="AEN813"
HREF="#FTN.AEN813"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>,
	there is a special structure to hold pointers to all those functions, <TT
CLASS="VARNAME"
>struct inode_operations</TT
>, which
	includes a pointer to <TT
CLASS="VARNAME"
>struct file_operations</TT
>. In /proc, whenever we register a new file, we're allowed to
	specify which <TT
CLASS="VARNAME"
>struct inode_operations</TT
> will be used for access to it. This is the mechanism we use, a
	<TT
CLASS="VARNAME"
>struct inode_operations</TT
> which includes a pointer to a <TT
CLASS="VARNAME"
>struct file_operations</TT
> which
	includes pointers to our <TT
CLASS="FUNCTION"
>module_input</TT
> and <TT
CLASS="FUNCTION"
>module_output</TT
> functions.</P
><A
NAME="AEN822"
></A
><A
NAME="AEN825"
></A
><A
NAME="AEN827"
></A
><A
NAME="AEN830"
></A
><A
NAME="AEN833"
></A
><A
NAME="AEN836"
></A
><P
>It's important to note that the standard roles of read and write are reversed in the kernel. Read functions are used for
	output, whereas write functions are used for input. The reason for that is that read and write refer to the user's point of
	view --- if a process reads something from the kernel, then the kernel needs to output it, and if a process writes something
	to the kernel, then the kernel receives it as input.</P
><A
NAME="AEN840"
></A
><A
NAME="AEN843"
></A
><P
>Another interesting point here is the <TT
CLASS="FUNCTION"
>module_permission</TT
> function. This function is called whenever
	a process tries to do something with the <TT
CLASS="FILENAME"
>/proc</TT
> file, and it can decide whether to allow
	access or not. Right now it is only based on the operation and the uid of the current user (as available in
	<TT
CLASS="VARNAME"
>current</TT
>, a pointer to a structure which includes information on the currently running process), but it
	could be based on anything we like, such as what other processes are doing with the same file, the time of day, or the last
	input we received.</P
><A
NAME="AEN850"
></A
><A
NAME="AEN853"
></A
><A
NAME="AEN855"
></A
><P
>The reason for <TT
CLASS="FUNCTION"
>put_user</TT
> and <TT
CLASS="FUNCTION"
>get_user</TT
> is that Linux memory (under Intel
	architecture, it may be different under some other processors) is segmented.  This means that a pointer, by itself, does not
	reference a unique location in memory, only a location in a memory segment, and you need to know which memory segment it is to
	be able to use it. There is one memory segment for the kernel, and one of each of the processes.</P
><A
NAME="AEN861"
></A
><A
NAME="AEN864"
></A
><A
NAME="AEN867"
></A
><A
NAME="AEN869"
></A
><P
>The only memory segment accessible to a process is its own, so when writing regular programs to run as processes,
	there's no need to worry about segments. When you write a kernel module, normally you want to access the kernel memory
	segment, which is handled automatically by the system. However, when the content of a memory buffer needs to be passed between
	the currently running process and the kernel, the kernel function receives a pointer to the memory buffer which is in the
	process segment. The <TT
CLASS="FUNCTION"
>put_user</TT
> and <TT
CLASS="FUNCTION"
>get_user</TT
> macros allow you to access that
	memory.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN875"
></A
><P
><B
>Example 6-1. procfs.c</B
></P
><PRE
CLASS="PROGRAMLISTING"
>/* 
 *  procfs.c -  create a "file" in /proc, which allows both input and output.
 */
#include &#60;linux/kernel.h&#62;	/* We're doing kernel work */
#include &#60;linux/module.h&#62;	/* Specifically, a module */
#include &#60;linux/proc_fs.h&#62;	/* Necessary because we use proc fs */
#include &#60;asm/uaccess.h&#62;	/* for get_user and put_user */

/* 
 * Here we keep the last message received, to prove
 * that we can process our input 
 */
#define MESSAGE_LENGTH 80
static char Message[MESSAGE_LENGTH];
static struct proc_dir_entry *Our_Proc_File;

#define PROC_ENTRY_FILENAME "rw_test"

static ssize_t module_output(struct file *filp,	/* see include/linux/fs.h   */
			     char *buffer,	/* buffer to fill with data */
			     size_t length,	/* length of the buffer     */
			     loff_t * offset)
{
	static int finished = 0;
	int i;
	char message[MESSAGE_LENGTH + 30];

	/* 
	 * We return 0 to indicate end of file, that we have
	 * no more information. Otherwise, processes will
	 * continue to read from us in an endless loop. 
	 */
	if (finished) {
		finished = 0;
		return 0;
	}

	/* 
	 * We use put_user to copy the string from the kernel's
	 * memory segment to the memory segment of the process
	 * that called us. get_user, BTW, is
	 * used for the reverse. 
	 */
	sprintf(message, "Last input:%s", Message);
	for (i = 0; i &#60; length &#38;&#38; message[i]; i++)
		put_user(message[i], buffer + i);

	/* 
	 * Notice, we assume here that the size of the message
	 * is below len, or it will be received cut. In a real
	 * life situation, if the size of the message is less
	 * than len then we'd return len and on the second call
	 * start filling the buffer with the len+1'th byte of
	 * the message. 
	 */
	finished = 1;

	return i;		/* Return the number of bytes "read" */
}

static ssize_t
module_input(struct file *filp, const char *buff, size_t len, loff_t * off)
{
	int i;
	/* 
	 * Put the input into Message, where module_output
	 * will later be able to use it 
	 */
	for (i = 0; i &#60; MESSAGE_LENGTH - 1 &#38;&#38; i &#60; len; i++)
		get_user(Message[i], buff + i);

	Message[i] = '\0';	/* we want a standard, zero terminated string */
	return i;
}

/* 
 * This function decides whether to allow an operation
 * (return zero) or not allow it (return a non-zero
 * which indicates why it is not allowed).
 *
 * The operation can be one of the following values:
 * 0 - Execute (run the "file" - meaningless in our case)
 * 2 - Write (input to the kernel module)
 * 4 - Read (output from the kernel module)
 *
 * This is the real function that checks file
 * permissions. The permissions returned by ls -l are
 * for referece only, and can be overridden here.
 */

static int module_permission(struct inode *inode, int op, struct nameidata *foo)
{
	/* 
	 * We allow everybody to read from our module, but
	 * only root (uid 0) may write to it 
	 */
	if (op == 4 || (op == 2 &#38;&#38; current-&#62;euid == 0))
		return 0;

	/* 
	 * If it's anything else, access is denied 
	 */
	return -EACCES;
}

/* 
 * The file is opened - we don't really care about
 * that, but it does mean we need to increment the
 * module's reference count. 
 */
int module_open(struct inode *inode, struct file *file)
{
	try_module_get(THIS_MODULE);
	return 0;
}

/* 
 * The file is closed - again, interesting only because
 * of the reference count. 
 */
int module_close(struct inode *inode, struct file *file)
{
	module_put(THIS_MODULE);
	return 0;		/* success */
}

static struct file_operations File_Ops_4_Our_Proc_File = {
	.read = module_output,
	.write = module_input,
	.open = module_open,
	.release = module_close,
};

/* 
 * Inode operations for our proc file. We need it so
 * we'll have some place to specify the file operations
 * structure we want to use, and the function we use for
 * permissions. It's also possible to specify functions
 * to be called for anything else which could be done to
 * an inode (although we don't bother, we just put
 * NULL). 
 */

static struct inode_operations Inode_Ops_4_Our_Proc_File = {
	.permission = module_permission,	/* check for permissions */
};

/* 
 * Module initialization and cleanup 
 */
int init_module()
{
	int rv = 0;
	Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
	Our_Proc_File-&#62;owner = THIS_MODULE;
	Our_Proc_File-&#62;proc_iops = &#38;Inode_Ops_4_Our_Proc_File;
	Our_Proc_File-&#62;proc_fops = &#38;File_Ops_4_Our_Proc_File;
	Our_Proc_File-&#62;mode = S_IFREG | S_IRUGO | S_IWUSR;
	Our_Proc_File-&#62;uid = 0;
	Our_Proc_File-&#62;gid = 0;
	Our_Proc_File-&#62;size = 80;

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

	return rv;
}

void cleanup_module()
{
	remove_proc_entry(PROC_ENTRY_FILENAME, &#38;proc_root);
}</PRE
></DIV
><P
> Still hungry for procfs examples? Well, first of all keep in mind, there are rumors around, claiming
	that procfs is on it's way out, consider using sysfs instead. Second, if you really can't get enough, 
	there's a highly recommendable bonus level for procfs below <TT
CLASS="FILENAME"
> linux/Documentation/DocBook/ </TT
>. 
	Use <B
CLASS="COMMAND"
> make help </B
> in your toplevel kernel directory for instructions about how to convert it into 
	your favourite format. Example: <B
CLASS="COMMAND"
> make htmldocs </B
>. Consider using this mechanism, 
	in case you want to document something kernel related yourself.</P
></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.AEN813"
HREF="c792.htm#AEN813"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>The difference between the two is that file operations deal with
	the file itself, and inode operations deal with ways of referencing the file, such as creating links to it.</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="c745.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="c883.htm"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>The /proc File System</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Talking To Device Files</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>