【问题标题】:Why disabling interrupts achieves mutual exclusion in uni-processor systems?为什么禁用中断会在单处理器系统中实现互斥?
【发布时间】:2019-08-19 23:29:36
【问题描述】:

OSTEP 书籍the Locks Chapter 的第 28.5 节表明,禁用中断可实现单处理器系统中线程之间的互斥。我不明白:如果持有锁的线程在临界区调用一些系统调用怎么办?在这种情况下,它会在释放锁之前放弃 CPU,因此另一个等待锁的线程也可能进入临界区。我浏览了该部分,但找不到答案。

根据另一个lecture notesInternal events are thread does something to relinquish the CPUPreventing internal events is easy 的幻灯片2。然后幻灯片 3 通过禁用中断来解释与 OSTEP 书中相同的锁定实现。

虽然我有点确认确实有必要考虑持有锁的线程自己放弃CPU的情况,但我仍然有两个问题:

  1. 为什么上述两个参考中的实现只考虑禁用中断而忽略内部事件处理?
  2. 为什么内部事件容易预防?如何实现?我想出的唯一解决方案是阻止线程在临界区调用任何系统调用,这在我看来过于严格。

谁能与我分享智慧?

【问题讨论】:

    标签: multithreading concurrency operating-system locking


    【解决方案1】:

    在单处理器系统上不需要显式锁(如互斥锁或自旋锁)即可在短时间内实现对某物的独占访问。通过暂时禁用中断,您可以停止线程调度程序(因为它是中断驱动的),因此没有其他线程能够抢占使用禁用中断运行的代码。就这么简单。

    但是,系统可能会提供通过中断以外的方式触发线程调度的机制。比如说,有一个 yield 操作就是这样做的,它阻塞当前线程并解除阻塞另一个可以运行的线程。因此,禁用中断以实现独占/原子访问的代码不得使用任何此类操作,因为它们会破坏独占访问甚至使系统死锁(在 yield 之后,除非以某种方式重新启用中断,否则其他线程可能会无限期禁用中断运行在线程切换期间再次)。

    【讨论】:

    • 感谢您的回答。你的意思是程序员有责任不在临界区写任何yield操作吗?当程序员在临界区写yield时,操作系统根本不会警告程序员吗?
    • @ZLW 如果您可以任意禁用和启用中断,那么您已经可以搞砸系统了。警告(如果我从字面上理解你的话,我无法想象)可能太少太晚了。
    • @ZLW:当我编写协作调度程序时,我通常会包含一个安全检查来检测重入执行,尽管一旦检测到它实际上唯一可以做的就是杀死执行与诊断。在大多数情况下,操作屈服,他们需要其他任务来做某事才能继续,因此需要在关键部分屈服意味着代码将崩溃、死锁或违反关键部分的要求,而操作系统唯一希望做的就是选择发生哪些不良结果。
    【解决方案2】:

    为什么内部事件很容易预防?

    你引用了一张演讲幻灯片:

    根据另一个讲义的幻灯片2,内部事件是线程做一些事情来放弃CPU

    “线程一些事情来放弃CPU。”例如,线程进行阻塞系统调用。您可以通过不编写代码来防止这种情况发生,因为代码会在临界区中释放 CPU。

    【讨论】:

    • 你的意思是程序员有责任不编写任何在临界区放弃CPU的代码吗?当他这样做并且发生一些不良行为时,这完全是他的错,我们不应该责怪操作系统吗?
    • @ZLW,编写有效的代码是程序员的责任。当您在微控制器上处理原始实时操作系统时,这就是您编写有效代码的方式。当您处理具有完全抢占式调度和多个处理器的桌面/服务器/移动操作系统时,您可以使用互斥锁。
    • @ZLW:一个高质量的操作系统应该包括一个在关键区域内可以安全使用的系统调用列表,以及一个不安全的系统调用列表。类似的情况出现在经典 Macintosh OS 等协作多任务系统中。由托管句柄标识的未锁定对象可能会被任何分配内存的操作重新定位,但如果没有干预操作分配内存或对任何可能这样做的操作产生控制,代码可能会获取此类对象的地址并使用它而不首先锁定它。在这种情况下,有一个“安全”的调用列表。
    猜你喜欢
    • 2016-08-07
    • 2019-05-23
    • 2021-02-27
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 2012-03-27
    • 2023-03-22
    相关资源
    最近更新 更多