1

我正在写一个昏昏欲睡的驱动程序。在这里,任何尝试写入设备文件的进程都应该休眠用户提供的“n”秒。Reader 进程应该唤醒所有等待的进程。

编写器代码:

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;所以所有的 writer 进程都处于休眠状态,直到条件 flag[idn] == 1 变为真。这按预期工作。

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

为什么会这样?

4

1 回答 1

2

当 reader 进程执行flag[idn] = 0时,waitqueue 为空,但不保证唤醒的 writer 进程flag[idn] == 1已经检查了等待条件 ()。因此,写入进程可以看到标志为 0,并继续等待。

问题是,wait_event -family 宏在将等待添加到等待队列时使用autoremove_wake_function。该函数由 reader 在wake_up_interruptible () 调用中调用,并且除了将 writer 进程标记为已唤醒之外,还会立即从 waitqueue 中删除 wait

实际上,在 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

于 2015-04-21T07:31:01.900 回答