Linux设备驱动程序学习(10)-时间、延迟及延缓操作(Jit.c)

来源:互联网 发布:无人机软件开发 编辑:程序博客网 时间:2024/06/09 23:20
以下代碼基本演示了Linux设备驱动程序学习(10)-时间、延迟及延缓操作的所有知識

点击(此处)折叠或打开

  1. /*
  2.  * jit.-- the just-in-time module
  3.  *
  4.  * Copyright (C) 2001,2003 Alessandro Rubini and Jonathan Corbet
  5.  * Copyright (C) 2001,2003 O'Reilly & Associates
  6.  *
  7.  * The source code in this file can be freely used, adapted,
  8.  * and redistributed in source or binary form, so long as an
  9.  * acknowledgment appears in derived source files. The citation
  10.  * should list that the code comes from the book "Linux Device
  11.  * Drivers" by Alessandro Rubini and Jonathan Corbet, published
  12.  * by O'Reilly & Associates. No warranty is attached;
  13.  * we cannot take responsibility for errors or fitness for use.
  14.  *
  15.  * $Id: jit.c,v 1.16 2004/09/26 07:02:43 gregkh Exp $
  16.  */

  17. //#include <linux/config.h>
  18. #include <linux/module.h>
  19. #include <linux/moduleparam.h>
  20. #include <linux/init.h>

  21. #include <linux/time.h>
  22. #include <linux/timer.h>
  23. #include <linux/kernel.h>
  24. #include <linux/proc_fs.h>
  25. #include <linux/types.h>
  26. #include <linux/spinlock.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/sched.h>
  29. #include <asm/hardirq.h>
  30. /*
  31.  * This module is a silly one: it only embeds short code fragments
  32.  * that show how time delays can be handled in the kernel.
  33.  */

  34. int delay = HZ; /* s3c24x0 HZ= 200*/

  35. module_param(delay, int, 0);

  36. /* use these as data pointers, to implement four files in one function */
  37. enum jit_files {
  38.     JIT_BUSY,
  39.     JIT_SCHED,
  40.     JIT_QUEUE,
  41.     JIT_SCHEDTO
  42. };

  43. /*
  44.  * This function prints one line of data, after sleeping one second.
  45.  * It can sleep in different ways, according to the data pointer
  46.  */
  47. int jit_fn(char *buf, char **start, off_t offset,
  48.      int len, int *eof, void *data)
  49. {
  50.     unsigned long j0, j1; /* jiffies */
  51.     wait_queue_head_t wait;

  52.     init_waitqueue_head (&wait);
  53.     j0 = jiffies;
  54.     j1 = j0 + delay;

  55.     switch((long)data) {
  56.         case JIT_BUSY:
  57.             while (time_before(jiffies, j1))
  58.                 cpu_relax();
  59.                 printk("cpu_relax()n");
  60.             break;
  61.         case JIT_SCHED:
  62.             while (time_before(jiffies, j1)) {
  63.                 schedule();
  64.                 printk("schedule()n");
  65.             }
  66.             break;
  67.         case JIT_QUEUE:
  68.             wait_event_interruptible_timeout(wait, 0, delay);
  69.             printk("one wait event for %d s",delay);
  70.             break;
  71.         case JIT_SCHEDTO:
  72.             set_current_state(TASK_INTERRUPTIBLE);
  73.             schedule_timeout (delay);
  74.             printk("two wait event for %d s",delay);
  75.             break;
  76.     }
  77.     j1 = jiffies; /* actual value after we delayed */

  78.     len = sprintf(buf, "%9li %9lin", j0, j1);
  79.     *start = buf;
  80.     return len;
  81. }

  82. /*
  83.  * This file, on the other hand, returns the current time forever
  84.  */
  85. int jit_currentime(char *buf, char **start, off_t offset,
  86.                    int len, int *eof, void *data)
  87. {
  88.     struct timeval tv1;
  89.     struct timespec tv2;
  90.     unsigned long j1;
  91.     u64 j2;
  92.     

  93.     /* get them four */
  94.     j1 = jiffies;
  95.     j2 = get_jiffies_64();
  96.     //use two method to get the time
  97.     do_gettimeofday(&tv1);
  98.     tv2 = current_kernel_time();

  99.     /* print */
  100.     len=0;
  101.     printk("the length is : %dn",len);
  102.     len += sprintf(buf,"0x%08lx 0x%016Lx %10i.%06in"
  103.          "%40i.%09in",
  104.          j1, j2,
  105.          (int) tv1.tv_sec, (int) tv1.tv_usec,
  106.          (int) tv2.tv_sec, (int) tv2.tv_nsec);

  107.     //here you can choose to show the message till you don't want (know the use of start)
  108.     *start = buf; /*if you want currentime to output only onec ,disable this 

  109.     return len;
  110. }

  111. /*
  112.  * The timer example follows
  113.  */

  114. int tdelay = 10;
  115. module_param(tdelay, int, 0);

  116. /* This data structure used as "data" for the timer and tasklet functions */
  117. struct jit_data {
  118.     struct timer_list timer;
  119.     struct tasklet_struct tlet;
  120.     int hi; /* tasklet or tasklet_hi */
  121.     wait_queue_head_t wait;
  122.     unsigned long prevjiffies;
  123.     unsigned char *buf;
  124.     int loops;
  125. };
  126. #define JIT_ASYNC_LOOPS 5

  127. void jit_timer_fn(unsigned long arg)
  128. {
  129.     struct jit_data *data = (struct jit_data *)arg;
  130.     unsigned long j = jiffies;
  131.     data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %sn",
  132.              j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
  133.              current->pid, smp_processor_id(), current->comm);

  134.     if (--data->loops)
  135.     {
  136.         data->prevjiffies = j;
  137.         mod_timer(&data->timer, data->timer.expires+tdelay);
  138.     } 
  139.     else 
  140.     {
  141.         wake_up_interruptible(&data->wait);
  142.     }
  143. }

  144. /* the /proc function: allocate everything to allow concurrency */
  145. int jit_timer(char *buf, char **start, off_t offset,
  146.      int len, int *eof, void *unused_data)
  147. {
  148.     struct jit_data *data;
  149.     char *buf2 = buf;
  150.     unsigned long j = jiffies;

  151.     data = kmalloc(sizeof(*data), GFP_KERNEL);
  152.     if (!data)
  153.         return -ENOMEM;

  154.     init_timer(&data->timer);
  155.     init_waitqueue_head (&data->wait);

  156.     /* write the first lines in the buffer */
  157.     buf2 += sprintf(buf2, " time delta inirq pid cpu commandn");
  158.     buf2 += sprintf(buf2, "%9li %3li %i %6i %i %sn",
  159.             j, 0L, in_interrupt() ? 1 : 0,
  160.             current->pid, smp_processor_id(), current->comm);

  161.     /* fill the data for our timer function */
  162.     data->prevjiffies = j;
  163.     data->buf = buf2;
  164.     data->loops = JIT_ASYNC_LOOPS;
  165.     
  166.     /* register the timer */
  167.     data->timer.data = (unsigned long)data;
  168.     data->timer.function = jit_timer_fn;
  169.     data->timer.expires = j + tdelay; /* parameter */
  170.     add_timer(&data->timer);

  171.     /* wait for the buffer to fill */
  172.     wait_event_interruptible(data->wait, !data->loops);
  173.     if (signal_pending(current))
  174.         return -ERESTARTSYS;
  175.     buf2 = data->buf;
  176.     //del_timer(&data->timer);
  177.     kfree(data);
  178.     *eof = 1;
  179.     return buf2 - buf;
  180. }

  181. void jit_tasklet_fn(unsigned long arg)
  182. {
  183.     struct jit_data *data = (struct jit_data *)arg;
  184.     unsigned long j = jiffies;
  185.     data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %sn",
  186.              j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
  187.              current->pid, smp_processor_id(), current->comm);

  188.     if (--data->loops) {
  189.         data->prevjiffies = j;
  190.         if (data->hi)
  191.             tasklet_hi_schedule(&data->tlet);
  192.         else
  193.             tasklet_schedule(&data->tlet);
  194.     }
  195.     else 
  196.     {
  197.         wake_up_interruptible(&data->wait);
  198.     }
  199. }

  200. /* the /proc function: allocate everything to allow concurrency */
  201. int jit_tasklet(char *buf, char **start, off_t offset,
  202.      int len, int *eof, void *arg)
  203. {
  204.     struct jit_data *data;
  205.     char *buf2 = buf;
  206.     unsigned long j = jiffies;
  207.     long hi = (long)arg;

  208.     data = kmalloc(sizeof(*data), GFP_KERNEL);
  209.     if (!data)
  210.         return -ENOMEM;

  211.     init_waitqueue_head (&data->wait);

  212.     /* write the first lines in the buffer */
  213.     buf2 += sprintf(buf2, " time delta inirq pid cpu commandn");
  214.     buf2 += sprintf(buf2, "%9li %3li %i %6i %i %sn",
  215.             j, 0L, in_interrupt() ? 1 : 0,
  216.             current->pid, smp_processor_id(), current->comm);

  217.     /* fill the data for our tasklet function */
  218.     data->prevjiffies = j;
  219.     data->buf = buf2;
  220.     data->loops = JIT_ASYNC_LOOPS;
  221.     
  222.     /* register the tasklet */
  223.     tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);
  224.     data->hi = hi;
  225.     if (hi)
  226.         tasklet_hi_schedule(&data->tlet);
  227.     else
  228.         tasklet_schedule(&data->tlet);

  229.     /* wait for the buffer to fill */
  230.     wait_event_interruptible(data->wait, !data->loops);

  231.     if (signal_pending(current))
  232.         return -ERESTARTSYS;
  233.     buf2 = data->buf;
  234.     kfree(data);
  235.     *eof = 1;
  236.     return buf2 - buf;
  237. }



  238. int __init jit_init(void)
  239. {
  240.     create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);

  241.     //the method to use tranamit a data
  242.     create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY/*pay more attention here*/);
  243.     create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);
  244.     create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);
  245.     create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);

  246.     create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);
  247.     create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
  248.     create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);

  249.     return 0; /* success */
  250. }

  251. void __exit jit_cleanup(void)
  252. {
  253.     remove_proc_entry("currentime", NULL);
  254.     remove_proc_entry("jitbusy", NULL);
  255.     remove_proc_entry("jitsched", NULL);
  256.     remove_proc_entry("jitqueue", NULL);
  257.     remove_proc_entry("jitschedto", NULL);

  258.     remove_proc_entry("jitimer", NULL);
  259.     remove_proc_entry("jitasklet", NULL);
  260.     remove_proc_entry("jitasklethi", NULL);
  261. }

  262. module_init(jit_init);
  263. module_exit(jit_cleanup);

  264. MODULE_AUTHOR("Alessandro Rubini ( modified by tekkaman )");
  265. MODULE_LICENSE("Dual BSD/GPL");
0 0
原创粉丝点击