我正在阅读 Robert Love 的《Linux 内核开发》,并找到下面的代码来等待事件。
DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) {
// What happens if condition is changed and wake_up() is called here ?
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if (signal_pending(current))
/* handle signal */
schedule();
}
finish_wait(&q, &wait);
Run Code Online (Sandbox Code Playgroud)
我的问题如上面的代码所示。如果条件更改并wake_up()在条件检查之后但之前调用,会发生什么情况prepare_to_wait?我在这里的(可能是错误的)解释是,因为在条件改变后prepare_to_wait创建线程TASK_INTERRUPTIBLE并调用,所以它永远休眠(除非它收到信号或调用另一个线程)。schedule()wake_up
是的,这段代码实际上是在和 之间进行了竞争,调用它应该是检查(如果满足则中断)。prepare_to_waitschedulecondition
inotify_read()有趣的是,在以下描述中,本书提到(第 60 页)文件中函数的实现fs/notify/inotify/inotify_user.c:
DEFINE_WAIT(wait);
...
while (1) {
prepare_to_wait(&group->notification_waitq,
&wait,
TASK_INTERRUPTIBLE);
if (<condition>) // very simplified form of checks
break;
if (signal_pending(current))
break;
schedule();
}
finish_wait(&group->notification_waitq, &wait);
...
Run Code Online (Sandbox Code Playgroud)
根据作者的说法,它“遵循模式”:
该函数遵循我们示例中列出的模式。主要区别在于它检查循环体中的条件
while(),而不是while()语句本身。这是因为检查条件很复杂并且需要抢锁。循环通过 终止break。
然而,该代码展示了另一种模式prepare_to_wait,它检查和调用之间的条件schedule。该代码实际上是正确的(无竞争)。此外,该代码不使用add_wait_queue,这在存在 的情况下是多余的prepare_to_wait。
在同一作者的另一本书《Linux Driver Development (3d revision)》中,等待队列的用法似乎更准确。例如,请参见第 6 章“高级字符驱动程序操作”。
| 归档时间: |
|
| 查看次数: |
653 次 |
| 最近记录: |