⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node21.html

📁 Linux可卸载模块编程
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!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>Blocking Processes</TITLE>
<META NAME="description" CONTENT="Blocking Processes">
<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="node22.html">
<LINK REL="previous" HREF="node20.html">
<LINK REL="up" HREF="mpg.html">
<LINK REL="next" HREF="node22.html">
</HEAD>
<BODY >
<!--Navigation Panel-->
<A NAME="tex2html635"
 HREF="node22.html">
<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
 SRC="next_motif.gif"></A> 
<A NAME="tex2html631"
 HREF="mpg.html">
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
 SRC="up_motif.gif"></A> 
<A NAME="tex2html625"
 HREF="node20.html">
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
 SRC="previous_motif.gif"></A> 
<A NAME="tex2html633"
 HREF="node1.html">
<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents"
 SRC="contents_motif.gif"></A> 
<A NAME="tex2html634"
 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="tex2html636"
 HREF="node22.html">Replacing printk's</A>
<B> Up:</B> <A NAME="tex2html632"
 HREF="mpg.html">Linux Kernel Module Programming</A>
<B> Previous:</B> <A NAME="tex2html626"
 HREF="node20.html">System Calls</A>
<BR>
<BR>
<!--End of Navigation Panel-->

<H1><A NAME="SECTION001000000000000000000">&#160;</A><A NAME="blocks">&#160;</A><A NAME="550">&#160;</A>
<A NAME="551">&#160;</A>
<BR>
Blocking Processes
</H1>

<P>
What do you do when somebody asks you for something you can't do right away?
If you're a human being and you're bothered by a human being, the only thing
you can say is: `Not right now, I'm busy. <EM>Go away!</EM>'. But if you're 
a kernel module and you're bothered by a process, you have another 
possibility. You can put the process to sleep until you can service it. 
After all, processes are being put to sleep by the kernel and woken up all 
the time 
(that's the way multiple processes appear to run on the same time on a 
single CPU). 
<A NAME="553">&#160;</A>
<A NAME="554">&#160;</A>

<P>
This kernel module is an example of this. The file (called <TT>/proc/sleep</TT>) 
can only be opened by a single process at a time. If the file is already
open, the kernel module calls 
<TT>module_interruptible_sleep_on</TT><A NAME="tex2html186"
 HREF="footnode.html#foot852"><SUP>8.1</SUP></A>. This 
function changes the status of the task (a task is the kernel data structure 
which holds
information about a process and the system call it's in, if any) to 
<TT>TASK_INTERRUPTIBLE</TT>, which means that the task will not run until 
it is woken
up somehow, and adds it to <TT>WaitQ</TT>, the queue of tasks waiting to 
access the 
file. Then, the function calls the scheduler to context switch to a 
different process, one which has some use for the CPU.
<A NAME="560">&#160;</A>
<A NAME="561">&#160;</A>
<A NAME="562">&#160;</A>
<A NAME="563">&#160;</A>
<A NAME="564">&#160;</A>
<A NAME="565">&#160;</A>
<A NAME="566">&#160;</A>
<A NAME="567">&#160;</A>

<P>
When a process is done with the file, it closes it, and <TT>module_close</TT> is
called. That function wakes up all the processes in the queue (there's no
mechanism to only wake up one of them). It then returns and the 
process which just closed the file can continue to run. In time, the 
scheduler decides that that process has had enough and gives control of 
the CPU to another process. Eventually, one of the processes which was
in the queue will be given control of the CPU by the scheduler.
It starts at the point right after the call to 
<TT>module_interruptible_sleep_on</TT>
<A NAME="tex2html195"
 HREF="footnode.html#foot853"><SUP>8.2</SUP></A>
. It can then proceed to set a global variable
to tell all the other processes that the file is still open and go on with
its life. When the other processes get a piece of the CPU, they'll see that
global variable and go back to sleep.
<A NAME="571">&#160;</A>
<A NAME="572">&#160;</A>
<A NAME="573">&#160;</A>
<A NAME="574">&#160;</A>

<P>
To make our life more interesting, <TT>module_close</TT> doesn't have a 
monopoly on
waking up the processes which wait to access the file. A signal, such as 
Ctrl-C (<TT>SIGINT</TT>) can also wake up a process<A NAME="tex2html200"
 HREF="footnode.html#foot854"><SUP>8.3</SUP></A>. In that case, we want to 
return
with <TT>-EINTR</TT> immediately. This is important so users can, for example, 
kill the process before it receives the file.
<A NAME="580">&#160;</A>
<A NAME="581">&#160;</A>
<A NAME="582">&#160;</A>
<A NAME="583">&#160;</A>
<A NAME="584">&#160;</A>
<A NAME="585">&#160;</A>
<A NAME="586">&#160;</A>
<A NAME="587">&#160;</A>

<P>
There is one more point to remember. Some times processes don't want to
sleep, they want either to get what they want immediately, or to be told
it cannot be done. Such processes use the <TT>O_NONBLOCK</TT> 
flag when opening the file. The kernel is supposed to respond by returning
with the error code <TT>-EAGAIN</TT> from operations which would otherwise 
block, such as opening the file in this example. The program cat_noblock,
available in the source directory for this chapter, can be used to open
a file with <TT>O_NONBLOCK</TT>.
<A NAME="591">&#160;</A> 
<A NAME="592">&#160;</A>
<A NAME="593">&#160;</A>
<A NAME="594">&#160;</A>

<P>
ex
 
<FONT SIZE="+1"><B>sleep.c</B></FONT> 
<A NAME="599">&#160;</A><A NAME="600">&#160;</A> 

<P>
<PRE>
 
/* sleep.c - create a /proc file, and if several 
 * processes try to open it at the same time, put all 
 * but one to sleep */


/* Copyright (C) 1998-99 by Ori Pomerantz */


/* The necessary header files */

/* Standard in kernel modules */
#include &lt;linux/kernel.h&gt;   /* We're doing kernel work */
#include &lt;linux/module.h&gt;   /* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include &lt;linux/modversions.h&gt;
#endif        

/* Necessary because we use proc fs */
#include &lt;linux/proc_fs.h&gt;

/* For putting processes to sleep and waking them up */
#include &lt;linux/sched.h&gt;
#include &lt;linux/wrapper.h&gt;



/* 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 &gt;= KERNEL_VERSION(2,2,0)
#include &lt;asm/uaccess.h&gt;  /* 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 &gt;= 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];

  /* Return 0 to signify end of file - that we have 
   * nothing more to say at this point. */
  if (finished) {
    finished = 0;
    return 0;
  }

  /* If you don't understand this by now, you're 
   * hopeless as a kernel  programmer. */
  sprintf(message, "Last input:%s\n", Message);
  for(i=0; i&lt;len &amp;&amp; message[i]; i++) 
    put_user(message[i], buf+i);

  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 &gt;= KERNEL_VERSION(2,2,0)
static ssize_t module_input(
    struct file *file,   /* The file itself */
    const char *buf,     /* The buffer with input */
    size_t length,       /* The buffer's length */
    loff_t *offset)      /* offset to file - ignore */
#else
static int module_input(
    struct inode *inode, /* The file's inode */
    struct file *file,   /* The file itself */
    const char *buf,     /* The buffer with the input */
    int length)          /* The buffer's length */
#endif
{
  int i;

  /* Put the input into Message, where module_output 
   * will later be able to use it */
  for(i=0; i&lt;MESSAGE_LENGTH-1 &amp;&amp; i&lt;length; i++)
#if LINUX_VERSION_CODE &gt;= KERNEL_VERSION(2,2,0)
     get_user(Message[i], buf+i);
#else
  Message[i] = get_user(buf+i);
#endif
/* we want a standard, zero terminated string */
  Message[i] = '\0';  
  
  /* We need to return the number of input 
   * characters used */
  return i;
}

/* 1 if the file is currently open by somebody */
int Already_Open = 0;

/* Queue of processes who want our file */
static struct wait_queue *WaitQ = NULL;


/* Called when the /proc file is opened */
static int module_open(struct inode *inode,
                       struct file *file)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -