wait_event_interruptible() 和 wake_up()的使用 (转载)

1. 关于 wait_event_interruptible() 和 wake_up()的使用
  
读一下wait_event_interruptible()的源码,不难发现这个函数先将
当前进程的状态设置成TASK_INTERRUPTIBLE,然后调用schedule(),
而schedule()会将位于TASK_INTERRUPTIBLE状态的当前进程从runqueue
队列中删除。从runqueue队列中删除的结果是,当前这个进程将不再参
与调度,除非通过其他函数将这个进程重新放入这个runqueue队列中,
这就是wake_up()的作用了。
  
由于这一段代码位于一个由condition控制的for(;;)循环中,所以当由
shedule()返回时(当然是被wake_up之后,通过其他进程的schedule()而
再次调度本进程),如果条件condition不满足,本进程将自动再次被设
置为TASK_INTERRUPTIBLE状态,接下来执行schedule()的结果是再次被
从runqueue队列中删除。这时候就需要再次通过wake_up重新添加到
runqueue队列中。
  
如此反复,直到condition为真的时候被wake_up.
  
可见,成功地唤醒一个被wait_event_interruptible()的进程,需要满足:
  
   在 1)condition为真的前提下,2) 调用wake_up()。

所以,如果你仅仅修改condition,那么只是满足其中一个条件,这个时候,
被wait_event_interruptible()起来的进程尚未位于runqueue队列中,因
此不会被 schedule。这个时候只要wake_up一下就立刻会重新进入运行调度。
  
2. 关于wait_event_interruptible的返回值
  
根据 wait_event_interruptible 的宏定义知:
  
   1) 条件condition为真时调用这个函数将直接返回0,而当前进程不会
      被 wait_event_interruptible和从runqueue队列中删除。
  
   2) 如果要被wait_event_interruptible的当前进程有nonblocked pending
      signals, 那么会直接返回-ERESTARTSYS(i.e. -512),当前进程不会
      被wait_event_interruptible 和从runqueue队列中删除。
  
   3) 其他情况下,当前进程会被正常的wait_event_interruptible,并从
      runqueue队列中删除,进入TASK_INTERRUPTIBLE状态退出运行调度,
      直到再次被唤醒加入runqueue队列中后而参与调度,将正常返回0。

 

 

 

TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE 的区别
TASK_INTERRUPTIBLE是可以被信号和wake_up()唤醒的,当信号到来时,进程会被设置为可运行。
而TASK_UNINTERRUPTIBLE只能被wake_up()唤醒。

信号本质

 

信号是在软件层次上对中断机制的一种模拟,软中断

 

信号来源

 

信号事件的发生有两个来源:

 

硬件来源:(比如我们按下了键盘或者其它硬件故障);

 

软件来源:最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。

 

区分是什么原因唤醒进程,用signal_pending( current );

 

检查当前进程是否有信号处理,返回不为0表示有信号需要处理。-ERESTARTSYS 表示信号函数处理完毕后重新执行信号函数前的某个系统调用。也就是说,如果信号函数前有发生系统调用,在调度用户信号函数之前,内核会检查系统调用的返回值,看看是不是因为这个信号而中断了系统调用.如果返回值-ERESTARTSYS,并且当前调度的信号具备-ERESTARTSYS属性,系统就会在用户信号函数返回之后再执行该系统调用。

 

posted @ 2015-08-14 15:25  knightsoul  阅读(2906)  评论(0)    收藏  举报