我是内核新手。我在阅读源代码时遇到了这个问题。
在wait_event()
的实现中,内核执行类似这样的操作:
...
prepare_to_wait(); /* enqueue current thread to the wait queue */
...
schedule(); /* invoke deactivate_task() inside, which will dequeue current thread from the runqueue */
...
在执行“wake_up()”时,内核执行以下操作:
...
try_to_wake_up(); /* invoke activate_task() inside, which will enqueue the target thread into the runqueue */
...
在并发执行中,如果按以下顺序调用上述函数,该怎么办:
...
prepare_to_wait(); /* thread A adds itself to the wait queue */
...
try_to_wake_up(); /* thread B wakes up A and enqueues it into the runqueue */
...
schedule(); /* thread A dequeues itself from the runqueue and yields the CPU */
...
线程A不在runqueue或等待队列中。这是否意味着我们丢失了线程A?内核必须有一些机制来防止这种情况发生。有人能告诉我在这里错过了什么吗?谢谢!
答案 0 :(得分:3)
我在2005年7月28日由 Kedar Sovani 撰写的Kernel Korner - Sleeping in the Kernel in Issue 137 of the Linux Journal文章中找到了答案。
简而言之,这是丢失的唤醒问题。 Linux内核通过将任务状态设置为 TASK_INTERRUPTIBLE 来解决此问题。这会导致呼叫schedule()
立即唤醒,即使有人在schedule()
呼叫之前呼叫唤醒功能[以及正常期间]。
答案 1 :(得分:0)
内核的一种机制是wait_event *()宏。它以Kernel Korner - Sleeping in the Kernel
中所述的方式工作