问题描述
我正在写一个困的司机.在这里,任何尝试写入设备文件的进程都应休眠用户提供的"n"秒数.阅读器进程应唤醒所有等待的进程.
I am writing a sleepy driver. Here any process that tries to write to the device file should sleep for 'n' number of seconds supplied by the user. Reader process should wake up all the waiting processes.
作者代码:
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;因此,所有编写器进程都会进入睡眠状态,直到条件flag [idn] == 1变为真.一切正常.
Initially flag[0] = 0; So all the writer processes sleep till the condition flag[idn] == 1 become true. This is working as expected.
但是在阅读器代码中,我将flag [idn]设置为1并调用ake_up_interruptible()来唤醒所有在该条件下休眠的进程.但这并没有唤醒睡眠过程.但是,如果我在while(waitqueue_active(& wq [idn]))下面取出flag [idn] = 0,则它正在工作,即函数正在唤醒睡眠过程.
But in reader code, I am setting flag[idn] = 1 and invoking wake_up_interruptible() to wake all processes sleeping on the condition. But this is not waking up the sleeping processes. But if I take out flag[idn] = 0 just below while(waitqueue_active(&wq[idn])), it is working i.e, function is waking up the sleeping processes.
为什么会这样?
推荐答案
当读取器进程执行flag[idn] = 0
时,waitqueue为空,但没有保证唤醒的写入器进程已具有等待条件(flag[idn] == 1
).因此,编写器进程可以看到该标志为0,并继续等待.
When reader process executes flag[idn] = 0
, waitqueue is empty, but there is no garantee that awoken writer process has wait condition (flag[idn] == 1
) already checked. So, writer process can see that flag is 0, and continues waiting.
问题是,在等待队列中添加等待时, wait_event 系列宏使用 autoremove_wake_function .读取器在 wake_up_interruptible ()调用中调用此函数,除了标记编写器进程被唤醒以外,立即从等待队列中删除等待.
The thing is that, wait_event-family macros use autoremove_wake_function when add wait into the waitqueue. This function is called by the reader at wake_up_interruptible() call and, aside from marks writer process as awoken, immediately removes wait from the waitqueue.
实际上,无论如何,在wake_up()之后重置等待条件是个坏主意:结果代码的语义含糊不清,可能会遇到竞争条件.
Actually, reseting wait condition after wake_up() is a bad idea anyway: resulted code has obscure semantic, and likely suffers from race conditions.
要获得可重复唤醒的效果,可以使用以下代码:
For achive effect with repeatable awoken, you can use this code:
作家:
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
.
Here writer process always waits at least one reader process is executed.Note, that flag[idn]++
now doesn't reset wait condition flag[idn] != cflag
.
这篇关于wake_up_interruptible()不会唤醒处于条件下休眠的进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!