wake_up_interruptible()没有唤醒正在休眠的进程

时间:2015-04-21 05:33:45

标签: linux-kernel kernel driver linux-device-driver wakeup

我正在写一个沉睡的司机。在这里,尝试写入设备文件的任何进程都应该为“ ' n用户提供的秒数。读者流程应该唤醒所有等待过程。

作家代码:

printk("Invoking interruptible_timeout for device flag[%d] = %d\n", idn, flag[idn]);
long ret = wait_event_interruptible_timeout(wq[idn],flag[idn]==1,sec*HZ)/HZ;
//flag[idn]=0;
printk("timeout returned : %d   idn = %d\n", ret, idn)
printk("writer : flag[%d] = %d\n", idn, flag[idn]);
retval=ret;

读者代码:

printk("waking up process with idn = %d\n", idn);
flag[idn]=1;
printk("reader : flag[%d] = %d \n", idn, flag[idn]);
wake_up_interruptible(&wq[idn]);
while(waitqueue_active(&wq[idn]));
flag[idn] = 0;
printk("returned from wake_up_interruptible \n");
printk("reader : flag[%d] = %d \n", idn, flag[idn]);

最初标志[0] = 0;所以所有的编写器进程都会睡眠,直到条件标志[idn] == 1变为真。这是按预期工作的。

但是在读者代码中,我设置了标志[idn] = 1并调用wake_up_interruptible()来唤醒在该条件下休眠的所有进程。但这并没有唤醒沉睡的过程。但是,如果我在下面取出标志[idn] = 0(waitqueue_active(& wq [idn])),它正在工作,即函数正在唤醒睡眠过程。

为什么会这样?

1 个答案:

答案 0 :(得分:2)

当读取器进程执行flag[idn] = 0时,waitqueue为空,但是没有保证唤醒编写器进程已经检查了等待条件(flag[idn] == 1)。因此,编写器进程可以看到该标志为0,并继续等待。

问题是, wait_event -family宏在等待等待时添加等待时使用 autoremove_wake_function 。阅读器在 wake_up_interruptible ()调用时调用此函数,除了标记编写器进程唤醒之外,立即从等待队列中删除等待

实际上,在wake_up()之后重置等待条件无论如何都是一个坏主意:结果代码具有模糊的语义,并且可能会受到竞争条件的影响。

对于可重复唤醒的效果,您可以使用以下代码:

编剧:

int cflag = flag[idn];
wait_event_interruptible_timeout(&wq[idn], flag[idn] != cflag, sec*HZ);

阅读器:

flag[idn]++;
wake_up_interruptible_all(&wq[idn]);

这里编写进程总是等待执行至少一个读者进程。 请注意,flag[idn]++现在不会重置等待条件flag[idn] != cflag