📄 node17.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--Converted with LaTeX2HTML 98.1 release (February 19th, 1998)
originally by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds
* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>Using /proc For Input</TITLE>
<META NAME="description" CONTENT="Using /proc For Input">
<META NAME="keywords" CONTENT="mpg">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<LINK REL="STYLESHEET" HREF="mpg.css">
<LINK REL="next" HREF="node18.html">
<LINK REL="previous" HREF="node16.html">
<LINK REL="up" HREF="mpg.html">
<LINK REL="next" HREF="node18.html">
</HEAD>
<BODY >
<!--Navigation Panel-->
<A NAME="tex2html587"
HREF="node18.html">
<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
SRC="next_motif.gif"></A>
<A NAME="tex2html583"
HREF="mpg.html">
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
SRC="up_motif.gif"></A>
<A NAME="tex2html577"
HREF="node16.html">
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
SRC="previous_motif.gif"></A>
<A NAME="tex2html585"
HREF="node1.html">
<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents"
SRC="contents_motif.gif"></A>
<A NAME="tex2html586"
HREF="node34.html">
<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
SRC="index_motif.gif"></A>
<BR>
<B> Next:</B> <A NAME="tex2html588"
HREF="node18.html">Talking to Device Files</A>
<B> Up:</B> <A NAME="tex2html584"
HREF="mpg.html">Linux Kernel Module Programming</A>
<B> Previous:</B> <A NAME="tex2html578"
HREF="node16.html">The /proc File System</A>
<BR>
<BR>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION00600000000000000000"> </A><A NAME="proc-input"> </A><A NAME="341"> </A>
<A NAME="342"> </A>
<A NAME="343"> </A>
<BR>
Using /proc For Input
</H1>
<P>
So far we have two ways to generate output from kernel modules: we can
register a device driver and <TT>mknod</TT> a device file, or we can create a
<TT>/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>/proc</TT> file.
<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>proc_dir_entry</TT> struct 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>/proc</TT> file, we need to use the standard filesystem
mechanism.
<A NAME="349"> </A>
<A NAME="350"> </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="tex2html108"
HREF="footnode.html#foot351"><SUP>4.1</SUP></A>, there is a special
structure to hold pointers to all those functions,
<TT>struct inode_operations</TT>, which includes a pointer to
<TT>struct file_operations</TT>. In /proc, whenever we register a new file,
we're allowed to specify which <TT>struct inode_operations</TT> will be used
for access to it. This is the mechanism we use, a
<TT>struct inode_operations</TT> which includes a
pointer to a <TT>struct file_operations</TT> which includes pointers to our
<TT>module_input</TT> and <TT>module_output</TT> functions.
<A NAME="359"> </A>
<A NAME="360"> </A>
<A NAME="361"> </A>
<A NAME="362"> </A>
<A NAME="363"> </A>
<A NAME="364"> </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.
<A NAME="365"> </A>
<A NAME="366"> </A>
<P>
Another interesting point here is the <TT>module_permission</TT> function. This
function is called whenever a process tries to do something with the
<TT>/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 used (as available
in <TT>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.
<A NAME="370"> </A>
<A NAME="371"> </A>
<A NAME="372"> </A>
<A NAME="373"> </A>
<P>
The reason for <TT>put_user</TT> and <TT>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.
<A NAME="376"> </A>
<A NAME="377"> </A>
<A NAME="378"> </A>
<A NAME="379"> </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>put_user</TT> and <TT>get_user</TT> macros allow you to
access that memory.
<P>
ex
<FONT SIZE="+1"><B>procfs.c</B></FONT>
<A NAME="386"> </A><A NAME="387"> </A>
<P>
<PRE>
/* procfs.c - create a "file" in /proc, which allows
* both input and output. */
/* Copyright (C) 1998-1999 by Ori Pomerantz */
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
/* Necessary because we use proc fs */
#include <linux/proc_fs.h>
/* In 2.2.3 /usr/include/linux/version.h includes a
* macro for this, but 2.0.35 doesn't - so I add it
* here if necessary. */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h> /* for get_user and put_user */
#endif
/* The module's file functions ********************** */
/* Here we keep the last message received, to prove
* that we can process our input */
#define MESSAGE_LENGTH 80
static char Message[MESSAGE_LENGTH];
/* Since we use the file operations struct, we can't
* use the special proc output provisions - we have to
* use a standard read function, which is this function */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t module_output(
struct file *file, /* The file read */
char *buf, /* The buffer to put data to (in the
* user segment) */
size_t len, /* The length of the buffer */
loff_t *offset) /* Offset in the file - ignore */
#else
static int module_output(
struct inode *inode, /* The inode read */
struct file *file, /* The file read */
char *buf, /* The buffer to put data to (in the
* user segment) */
int len) /* The length of the buffer */
#endif
{
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<len && message[i]; i++)
put_user(message[i], buf+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" */
}
/* This function receives input from the user when the
* user writes to the /proc file. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t module_input(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -