为什么操作系统需要阻塞队列进行任务调度?
由于每个信号量都有一个被它阻塞的任务队列,每当释放信号量(1次)时,队列中的任务可以直接添加回操作系统的就绪队列。
情况:
3个任务( T1 , T2 , T3 )都使用信号量 S 访问一些共享数据。
就绪队列:{ T1 , T2 , T3 }, S < / strong> = 1,{}。
操作系统 T1 。 T1 从 S 中获得1。
就绪队列:{ T2 , T3 , T1 }, S < / strong> = 0,{}。
操作系统 T2 。 T2 从 S 中取1,并被屏蔽。
就绪队列:{ T3 , T1 }, S = -1,{ T2 }。
操作系统 T3 。 T3 从 S 中取1,并被屏蔽。
就绪队列:{ T1 }, S = -2,{ T2 , T3 }。
操作系统 T1 。使用共享资源后, T1 会将1发布为 S 。
在发布到 S 时,操作系统会将 T2 添加回 Ready Queue 。
就绪队列:{ T2 , T1 }, S = -1,{ T3 }。
操作系统 T2 。使用共享资源后, T2 会将1发布为 S 。
在发布到 S 时,操作系统会将 T3 添加回 Ready Queue 。
就绪队列:{ T3 , T2 , T1 }, S < / strong> = 0,{}。
操作系统 T3 。 T3 在使用共享资源后将1发布为 S 。
就绪队列:{ T3 , T2 , T1 }, S < / strong> = 1,{}。
上述情况确实使用了 S 的阻止队列,但它没有使用任何全局阻止队列,就像全局就绪队列一样的操作系统。
那么,为什么操作系统维护/需要阻塞队列?
(或者,操作系统中引用的阻塞队列实际上是每个信号量的阻塞队列,并且没有全局阻塞队列?)
答案 0 :(得分:0)
好吧,如果我正确理解这个问题。
最简单的队列形式是建立在链表上的。如果它没有阻挡,则可能存在竞争条件。例如,假设我们有进程A和B.它们都调用fork。
A正在运行和分叉。
准备添加到列表中,列表的大小为2.(例子)
上下文切换到B.
B也分叉。
B准备添加到列表中,因为队列没有阻塞,列表的大小也是2。
B完成。
上下文切换到A.
结束。
队列将具有(无特定顺序){A,B,A-child}
但是B孩子会因为A-child覆盖它而丢失。
为了确保只能同时在列表中添加和删除一个任务,它必须是互斥的,因此我们需要阻止信号量。
但是如果你考虑一下,信号量已经是一个阻塞队列,因为在后端,它完全符合我们的需要。
信号量的后端基本上是'确保不会发生中断的东西'(在那里阻塞的最低级别形式),并且任何调用信号量的东西都将被添加到信号量中的队列中。
所以是的,操作系统需要阻塞队列。