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属性,系统就会在用户信号函数返回之后再执行该系统调用。

浙公网安备 33010602011771号