【问题标题】:wake_up_interruptible() is not waking up the processes sleeping on conditionwake_up_interruptible() 没有唤醒在条件下休眠的进程
【发布时间】:2015-06-28 02:44:52
【问题描述】:

我正在写一个昏昏欲睡的驱动程序。在这里,任何尝试写入设备文件的进程都应该休眠用户提供的“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,它正在工作,即函数正在唤醒睡眠进程。

为什么会这样?

【问题讨论】:

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


    【解决方案1】:

    当 reader 进程执行flag[idn] = 0 时,waitqueue 为空,但不保证唤醒的 writer 进程已经检查了等待条件 (flag[idn] == 1)。所以,writer 进程可以看到 flag 为 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

    【讨论】:

      猜你喜欢
      • 2014-08-02
      • 1970-01-01
      • 2022-01-03
      • 2011-08-05
      • 2012-08-15
      • 1970-01-01
      • 2021-09-11
      • 2011-03-28
      • 2014-07-15
      相关资源
      最近更新 更多