ibanez170和270:解析Linux内核的同步与互斥机制(7)

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 11:33:48

解析Linux内核的同步与互斥机制(7)

时间:2011-01-19 14:29   来源:中国IT实验室   收藏  复制分享 共有评论(0)条

  5.3 手工休眠的具体函数执行流

  特殊睡眠要求程序员手动处理所有上面的步骤. 它是一个繁琐的过程, 包含相当多的易出错的样板式的代码. 程序员如果愿意还是可能用那种方式手动睡眠。

  (1)创建和初始化一个等待队列。常由宏定义完成: DEFINE_WAIT(my_wait); /*name 是等待队列入口项的名字. 也可以用2步来做:*/ wait_queue_t my_wait; init_wait(&my_wait); /*常用的做法是放一个 DEFINE_WAIT 在循环的顶部,来实现休眠。*/

  (2)添加等待队列入口到队列,并设置进程状态: void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state); /*queue 和 wait 分别地是等待队列头和进程入口。state 是进程的新状态:TASK_INTERRUPTIBLE(可中断休眠,推荐)或TASK_UNINTERRUPTIBLE(不可中断休眠,不推荐)。*/ prepare_to_wait_exclusive

  (3)在检查确认仍然需要休眠之后调用 schedule

  schedule();

  (4)schedule 返回,重新判断等待条件,若为真则退出,否则继续schedule

  (5)条件满足退出后,确保状态为running,同时将进程从等待队列中删除。

  void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);

  5.4 wait_event_interruptible_exclusive

  为了避免手工编写上述复杂代码,内核提供了最常见的interruptible类型排他性等待函数。而对于非排他性的可以直接利用等待事件event系列函数。

  #define __wait_event_interruptible_exclusive(wq, condition, ret) \

  do { \

  DEFINE_WAIT(__wait); \

  \

  for (;;) { \

  prepare_to_wait_exclusive(&wq, &__wait, \

  TASK_INTERRUPTIBLE); \

  if (condition) \

  break; \

  if (!signal_pending(current)) { \

  schedule(); \

  continue; \

  } \

  ret = -ERESTARTSYS; \

  break; \

  } \

  finish_wait(&wq, &__wait); \

  } while (0)

  #define wait_event_interruptible_exclusive(wq, condition) \

  ({ \

  int __ret = 0; \

  if (!(condition)) \

  __wait_event_interruptible_exclusive(wq, condition, __ret);\

  __ret; \

  })

  6 Completion

  completion是一种轻量级的机制,它允许一个线程告诉另一个线程某个工作已经完成。代码必须包含。使用的代码如下:

  DECLARE_COMPLETION(my_completion);/* 创建completion(声明+初始化) */ struct completion my_completion;/* 动态声明completion 结构体*/ static inline void init_completion(&my_completion);/*动态初始化completion*/ void wait_for_completion(struct completion *c);/* 等待completion */ void complete(struct completion *c);/*唤醒一个等待completion的线程*/ void complete_all(struct completion *c);/*唤醒所有等待completion的线程*/ /*如果未使用completion_all,completion可重复使用;否则必须使用以下函数重新初始化completion*/ INIT_COMPLETION(struct completion c);/*快速重新初始化completion*/

  completion 的典型应用是模块退出时的内核线程终止。在这种模式,某些驱动程序的内部工作有一个内核线程在while(1)循环中完成。当内核准备清除该模块时,exit函数会告诉该线程退出并等待completion。为此内核包含了用于这种线程的一个特殊函数:

  void complete_and_exit(struct completion *c, long retval);