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

📄 14.html

📁 linux操作系统内核编程-----LINUX系统开发非常好的资料
💻 HTML
字号:
<html><head><title>黄金书屋</title><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><link rel="stylesheet" href="/goldnets.css"></head><body bgcolor="#E4EBF1"><center><a href="http://ad.myrice.com/RealMedia/ads/click_nx.ads/goldnets.myrice.com/banner1@Top" target=_blanck ><script language=JavaScript><!---todayd = new Date();var seconds = todayd.getTime();document.write("<img src=\"http://ad.myrice.com/RealMedia/ads/adstream_nx.ads/goldnets.myrice.com/banner1@Top?dd=seconds\" border=0 width=468 height=60>");//--></script></a></center><br><table width="756" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="#E4EBF1">  <tr>    <td colspan="2" valign="top" align="center">      <div align="center">        <table width="100%" border="0" cellspacing="0" cellpadding="0" height="52">          <tr>            <td valign="top"><br>              <div align="center">                <table width="100%" border="0" cellspacing="0" cellpadding="0">                  <tr>                    <td valign="bottom">                      <table width="100%" border="0" cellspacing="0" cellpadding="0">                        <tr>                          <td><a href="/index.html">首页</a>&gt;&gt; <font color="#CC0000"><a href="/book/152/1015178.html">Linux内核编程</a></font></td>                          <td width="22%"> <a href="/index.html">[ 点此回首页 ]</a></td>                        </tr>                        <tr>                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="2"></td>                        </tr>                        <tr bgcolor="#FFCC00">                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="1"></td>                        </tr>                        <tr>                          <td colspan="2"><img src="/image/1x1.gif" width="1" height="6"></td>                        </tr>                      </table>                    </td>                  </tr>                </table>                <br>                <table width="590" border="0" cellspacing="0" cellpadding="0">                  <tr>                    <td><center><a href='13.html'>上一页 </a>||<a href='15.html'>下一页</a></center><br><hr><div style=font-size:12pt><pre>                               10.调度任务
经常地,我们有必须定时做或者经常做的“家务事”。如果这个任务由一个进程完成,
我们可以把通过把它放入crontab文件而做到。如果这个任务由一个内核模块完成,我们有
两种可能的选择。第一种是把一个进程放入crontab文件,它将在必要的时候通过一个系统
调用唤醒模块,比如打开一个文件。然而,这样做时非常低效的,我们需要运行一个crontab
外的新进程,把一个新的执行表读入内存,而所有这些只是为了唤醒一个内存中的内核模块。
我们不需要这样做。我们可以创建一个函数,在每个时间中断时被调用。方法是创建
一个任务,包含在一个结构体tq_struct里,在此结构中包含一个指向函数入口地址的指针。
然后,我们使用queue_task把这个任务放入一个叫做tq_timer的任务列表中,这是一个在下
次时间中断时要执行的任务列表。因为我们希望这个函数被持续执行,我们需要在每次调用
厚把它放回tq_timer中以备下次时间中断。
这里还有一点需要记住。当一个模块被rmmod删除时,首先他的索引计数器被检查。
如果是0,就调用module_cleanup。然后,这个模块以及它的所有函数都从内存中删除。没
有人检查是否时钟的任务列表仍然包含指向这些函数的指针,而现在已不可用。很久以后(从
计算机看来,在人的眼睛里是很短的,可能是百分之一秒),内核有了一个时钟中断,试图
调用任务列表中的所有函数。不幸的是,这个函数已不存在。在多数情况下,它所在的内存
还未被使用,而你得到了一个极端错误的信息。但是,如果有别的代码出在相同的地址,情
况会非常糟糕。不幸的是,我们没有一个从任务列表中注销一个任务的方法。
既然cleanup_module函数不能返回一个错误马(它是void型函数),那么解决方法是就
不要让它返回。而是调用sleep_on或module_sleep_on(注10.1)把rmmod进程挂起。在此
之前,它设置一个变量通知在时钟中断时调用的函数停止附加自己。那么,在下次时钟中断
时,rmmod进程将被唤醒,而我们的函数已经不在队列中,这样就可以很安全的删除模块。
ex sched.c    
 
/* sched.c - scheduale a function to be called on 
 * every timer interrupt. */



/* Copyright (C) 1998 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 the proc fs */
#include <linux/proc_fs.h>

/* We scheduale tasks here */
#include <linux/tqueue.h>

/* We also need the ability to put ourselves to sleep 
 * and wake up later */
#include <linux/sched.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



/* The number of times the timer interrupt has been 
 * called so far */
static int TimerIntrpt = 0;


/* This is used by cleanup, to prevent the module from 
 * being unloaded while intrpt_routine is still in 
 * the task queue */
static struct wait_queue *WaitQ = NULL;

static void intrpt_routine(void *);


/* The task queue structure for this task, from tqueue.h */
static struct tq_struct Task = {
  NULL,   /* Next item in list - queue_task will do 
           * this for us */
  0,      /* A flag meaning we haven\'t been inserted 
           * into a task queue yet */
  intrpt_routine, /* The function to run */
  NULL    /* The void* parameter for that function */
};



/* This function will be called on every timer 
 * interrupt. Notice the void* pointer - task functions 
 * can be used for more than one purpose, each time 
 * getting a different parameter. */
static void intrpt_routine(void *irrelevant)
{
  /* Increment the counter */
  TimerIntrpt++;

  /* If cleanup wants us to die */
  if (WaitQ != NULL) 
    wake_up(&WaitQ);   /* Now cleanup_module can return */
  else
    /* Put ourselves back in the task queue */
    queue_task(&Task, &tq_timer);  
}




/* Put data into the proc fs file. */
int procfile_read(char *buffer, 
                  char **buffer_location, off_t offset, 
                  int buffer_length, int zero)
{
  int len;  /* The number of bytes actually used */

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

  static int count = 1;

  /* We give all of our information in one go, so if 
   * the anybody asks us if we have more information 
   * the answer should always be no. 
   */
  if (offset > 0)
    return 0;

  /* Fill the buffer and get its length */
  len = sprintf(my_buffer, 
                \"Timer was called %d times so far\\n\", 
                TimerIntrpt);
  count++;

  /* 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 = 
  {
    0, /* Inode number - ignore, it will be filled by 
        * proc_register_dynamic */
    5, /* Length of the file name */
    \"sched\", /* The file name */
    S_IFREG | S_IRUGO, 
    /* File mode - this is a regular file which can
     * be read by its owner, its group, and everybody
     * else */
    1,  /* Number of links (directories where 
         * the file is referenced) */
    0, 0,  /* The uid and gid for the file - we give 
            * it to root */
    80, /* The size of the file reported by ls. */
    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()
{
  /* Put the task in the tq_timer task queue, so it 
   * will be executed at next timer interrupt */
  queue_task(&Task, &tq_timer);

  /* Success if proc_register_dynamic is a success, 
   * failure otherwise */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
  return proc_register(&proc_root, &Our_Proc_File);
#else
  return proc_register_dynamic(&proc_root, &Our_Proc_File);
#endif
}


/* Cleanup */
void cleanup_module()
{
  /* Unregister our /proc file */
  proc_unregister(&proc_root, Our_Proc_File.low_ino);
  
  /* Sleep until intrpt_routine is called one last 
   * time. This is necessary, because otherwise we\'ll 
   * deallocate the memory holding intrpt_routine and
   * Task while tq_timer still references them. 
   * Notice that here we don\'t allow signals to 
   * interrupt us. 
   *
   * Since WaitQ is now not NULL, this automatically 
   * tells the interrupt routine it\'s time to die. */
 sleep_on(&WaitQ);
}</pre><hr><br><center><a href='13.html'>上一页 </a>||<a href='15.html'>下一页</a></center></div> </td>                  </tr>                </table>                <p>&nbsp; </p>                </div>            </td>          </tr>        </table>          <br>          <table border="0" width="75%"><tr><td align="right"><a href="/"><img src="/image2/logo_bottom.gif" border="0"></a></td></tr></table>          <hr size="1" align="center" color="#eecccc">          <br>        </div>      </div>      </td>  </tr></table>  <center><a href="http://ad.myrice.com/RealMedia/ads/click_nx.ads/goldnets.myrice.com/banner1@Bottom" target=_blanck ><script language=JavaScript><!---todayd = new Date();var seconds = todayd.getTime();document.write("<img src=\"http://ad.myrice.com/RealMedia/ads/adstream_nx.ads/goldnets.myrice.com/banner1@Bottom?dd=seconds\" border=0 width=468 height=60>");//--></script></a></center></body></html>

⌨️ 快捷键说明

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