歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux設備驅動之時間,延遲及延緩操作(實踐)

Linux設備驅動之時間,延遲及延緩操作(實踐)

日期:2017/3/1 10:21:45   编辑:Linux編程

一 jit.函數源碼

  1. /*
  2. * jit.c -- 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/module.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/init.h>
  20. #include <linux/time.h>
  21. #include <linux/timer.h>
  22. #include <linux/kernel.h>
  23. #include <linux/proc_fs.h>
  24. #include <linux/types.h>
  25. #include <linux/spinlock.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/param.h>
  28. #include <linux/wait.h>
  29. #include <linux/jiffies.h>
  30. #include <linux/sched.h>
  31. #include <asm/hardirq.h>
  32. /*
  33. * This module is a silly one: it only embeds short code fragments
  34. * that show how time delays can be handled in the kernel.
  35. */
  36. int delay = HZ; /* the default delay, expressed in jiffies */
  37. module_param(delay, int, 0);
  38. MODULE_AUTHOR("Alessandro Rubini");
  39. MODULE_LICENSE("Dual BSD/GPL");
  40. /* use these as data pointers, to implement four files in one function */
  41. enum jit_files {
  42. JIT_BUSY,
  43. JIT_SCHED,
  44. JIT_QUEUE,
  45. JIT_SCHEDTO
  46. };
  47. /*
  48. * This function prints one line of data, after sleeping one second.
  49. * It can sleep in different ways, according to the data pointer
  50. */
  51. int jit_fn(char *buf, char **start, off_t offset,
  52. int len, int *eof, void *data)
  53. {
  54. unsigned long j0, j1; /* jiffies */
  55. wait_queue_head_t wait;
  56. init_waitqueue_head (&wait);
  57. j0 = jiffies;
  58. j1 = j0 + delay;
  59. switch((long)data) {
  60. case JIT_BUSY:
  61. while (time_before(jiffies, j1))
  62. cpu_relax();
  63. break;
  64. case JIT_SCHED:
  65. while (time_before(jiffies, j1)) {
  66. schedule();
  67. }
  68. break;
  69. case JIT_QUEUE:
  70. wait_event_interruptible_timeout(wait, 0, delay);
  71. break;
  72. case JIT_SCHEDTO:
  73. set_current_state(TASK_INTERRUPTIBLE);
  74. schedule_timeout (delay);
  75. break;
  76. }
  77. j1 = jiffies; /* actual value after we delayed */
  78. len = sprintf(buf, "%9li %9li\n", 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. /* get them four */
  93. j1 = jiffies;
  94. j2 = get_jiffies_64();
  95. do_gettimeofday(&tv1);
  96. tv2 = current_kernel_time();
  97. /* print */
  98. len=0;
  99. len += sprintf(buf,"0x%08lx 0x%016Lx %10i.%06i\n"
  100. "%40i.%09i\n",
  101. j1, j2,
  102. (int) tv1.tv_sec, (int) tv1.tv_usec,
  103. (int) tv2.tv_sec, (int) tv2.tv_nsec);
  104. *start = buf;
  105. return len;
  106. }
  107. /*
  108. * The timer example follows
  109. */
  110. int tdelay = 10;
  111. module_param(tdelay, int, 0);
  112. /* This data structure used as "data" for the timer and tasklet functions */
  113. struct jit_data {
  114. struct timer_list timer;
  115. struct tasklet_struct tlet;
  116. int hi; /* tasklet or tasklet_hi */
  117. wait_queue_head_t wait;
  118. unsigned long prevjiffies;
  119. unsigned char *buf;
  120. int loops;
  121. };
  122. #define JIT_ASYNC_LOOPS 5
  123. void jit_timer_fn(unsigned long arg)
  124. {
  125. struct jit_data *data = (struct jit_data *)arg;
  126. unsigned long j = jiffies;
  127. data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %s\n",
  128. j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
  129. current->pid, smp_processor_id(), current->comm);
  130. if (--data->loops) {
  131. data->timer.expires += tdelay;
  132. data->prevjiffies = j;
  133. add_timer(&data->timer);
  134. } else {
  135. wake_up_interruptible(&data->wait);
  136. }
  137. }
  138. /* the /proc function: allocate everything to allow concurrency */
  139. int jit_timer(char *buf, char **start, off_t offset,
  140. int len, int *eof, void *unused_data)
  141. {
  142. struct jit_data *data;
  143. char *buf2 = buf;
  144. unsigned long j = jiffies;
  145. data = kmalloc(sizeof(*data), GFP_KERNEL);
  146. if (!data)
  147. return -ENOMEM;
  148. init_timer(&data->timer);
  149. init_waitqueue_head (&data->wait);
  150. /* write the first lines in the buffer */
  151. buf2 += sprintf(buf2, " time delta inirq pid cpu command\n");
  152. buf2 += sprintf(buf2, "%9li %3li %i %6i %i %s\n",
  153. j, 0L, in_interrupt() ? 1 : 0,
  154. current->pid, smp_processor_id(), current->comm);
  155. /* fill the data for our timer function */
  156. data->prevjiffies = j;
  157. data->buf = buf2;
  158. data->loops = JIT_ASYNC_LOOPS;
  159. /* register the timer */
  160. data->timer.data = (unsigned long)data;
  161. data->timer.function = jit_timer_fn;
  162. data->timer.expires = j + tdelay; /* parameter */
  163. add_timer(&data->timer);
  164. /* wait for the buffer to fill */
  165. wait_event_interruptible(data->wait, !data->loops);
  166. if (signal_pending(current))
  167. return -ERESTARTSYS;
  168. buf2 = data->buf;
  169. kfree(data);
  170. *eof = 1;
  171. return buf2 - buf;
  172. }
  173. void jit_tasklet_fn(unsigned long arg)
  174. {
  175. struct jit_data *data = (struct jit_data *)arg;
  176. unsigned long j = jiffies;
  177. data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %s\n",
  178. j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
  179. current->pid, smp_processor_id(), current->comm);
  180. if (--data->loops) {
  181. data->prevjiffies = j;
  182. if (data->hi)
  183. tasklet_hi_schedule(&data->tlet);
  184. else
  185. tasklet_schedule(&data->tlet);
  186. } else {
  187. wake_up_interruptible(&data->wait);
  188. }
  189. }
  190. /* the /proc function: allocate everything to allow concurrency */
  191. int jit_tasklet(char *buf, char **start, off_t offset,
  192. int len, int *eof, void *arg)
  193. {
  194. struct jit_data *data;
  195. char *buf2 = buf;
  196. unsigned long j = jiffies;
  197. long hi = (long)arg;
  198. data = kmalloc(sizeof(*data), GFP_KERNEL);
  199. if (!data)
  200. return -ENOMEM;
  201. init_waitqueue_head (&data->wait);
  202. /* write the first lines in the buffer */
  203. buf2 += sprintf(buf2, " time delta inirq pid cpu command\n");
  204. buf2 += sprintf(buf2, "%9li %3li %i %6i %i %s\n",
  205. j, 0L, in_interrupt() ? 1 : 0,
  206. current->pid, smp_processor_id(), current->comm);
  207. /* fill the data for our tasklet function */
  208. data->prevjiffies = j;
  209. data->buf = buf2;
  210. data->loops = JIT_ASYNC_LOOPS;
  211. /* register the tasklet */
  212. tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);
  213. data->hi = hi;
  214. if (hi)
  215. tasklet_hi_schedule(&data->tlet);
  216. else
  217. tasklet_schedule(&data->tlet);
  218. /* wait for the buffer to fill */
  219. wait_event_interruptible(data->wait, !data->loops);
  220. if (signal_pending(current))
  221. return -ERESTARTSYS;
  222. buf2 = data->buf;
  223. kfree(data);
  224. *eof = 1;
  225. return buf2 - buf;
  226. }
  227. int __init jit_init(void)
  228. {
  229. create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);
  230. create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY);
  231. create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);
  232. create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);
  233. create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);
  234. create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);
  235. create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
  236. create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);
  237. return 0; /* success */
  238. }
  239. void __exit jit_cleanup(void)
  240. {
  241. remove_proc_entry("currentime", NULL);
  242. remove_proc_entry("jitbusy", NULL);
  243. remove_proc_entry("jitsched", NULL);
  244. remove_proc_entry("jitqueue", NULL);
  245. remove_proc_entry("jitschedto", NULL);
  246. remove_proc_entry("jitimer", NULL);
  247. remove_proc_entry("jitasklet", NULL);
  248. remove_proc_entry("jitasklethi", NULL);
  249. }
  250. module_init(jit_init);
  251. module_exit(jit_cleanup);
Copyright © Linux教程網 All Rights Reserved