Linux 等待队列 - 独占和非独占的组合

Linux wait queue - Combination of exclusive and non-exclusive

今天在 class 我们研究了 Linux 中的等待队列,在谈论 exclusive/non-exclusive 等待时出现了一些有趣的事情。

有人问了一个问题: 如果等待队列中有一些进程处于独占状态而其他进程处于非独占状态,会发生什么情况。

讲师回答说wake_up()会遍历队列,唤醒所有非独占的进程,直到遇到独占的,就唤醒最后一个进程,然后停止。

例如: 设N,E,分别代表等待队列中的一个非独占和独占进程:

N - N - N - E - N - E - N - N 

讲师说前4个wait会被唤醒(N-N-N-E),内核会在第一个E后停止遍历。

这听起来很奇怪,因为 E 是独占的,这意味着它不想被其他任何人唤醒,在这种情况下,它 被其他人唤醒。

谷歌搜索问题得到以下结果:

When a wait queue is “woken up” all tasks on the wait queue are enabled for the scheduler. If a task is added to a wait queue using an exclusive function then the wake up call will only wake up one exclusive task leaving the others still waiting. If a mixture of exclusive tasks and non exclusive tasks are added to the queue then the wake up function will wake up any non exclusive tasks until it wakes up the exclusive task. The wakeup order is normally the reverse of the order in which tasks are added to the queue. https://blackfin.uclinux.org/doku.php?id=linux-kernel:wait_queues

哪个是正确的?真正的答案是完全不同的吗?

注意:在 class 中,我们讨论的是 Linux2.4.18-14、i386(如果系统需要其他信息,请发表评论)

N - N - N - E - N - E - N - N

首先要注意的是 WQ_FLAG_EXCLUSIVE 的条目被添加到队列的末尾而不是开头。因此,引用的示例从未发生过;等待队列总是排序:所有 Ns,然后所有 Es.

since E is exclusive, meaning it doesn't want to be woken up with anyone else, and in this case it is woken up with others

第二个需要注意的是,独占服务员不想被和其他独占服务员一起叫醒。可以推测,非独占服务员正在执行完全不重叠的工作,而独占服务员正在做相关的工作——也许他们都需要相同的共享资源,所以唤醒他们会导致 "thundering herd" 因为他们都在尝试同一个锁。

因此,您通过 Google 找到的内容是正确的。你被告知的大部分内容 是正确的,即 Linux 在唤醒它找到的第一个独占服务员后停止。然而,等待队列未按排他性排序的建议是不正确的。