代码之家  ›  专栏  ›  技术社区  ›  Emiliano

非抢占linux内核上的自旋锁

  •  4
  • Emiliano  · 技术社区  · 15 年前

    我无法理解:它不应该等同于在互斥上睡眠吗?例如,即使在非抢占式内核上,中断处理程序仍然可以执行,或者我可以调用一个函数,使原始线程进入睡眠状态。因此,空的spin\u锁调用并不像实现为互斥锁那样“安全”。

    4 回复  |  直到 15 年前
        1
  •  5
  •   Macmade    12 年前

    引自 Linux设备驱动程序

    如果一个非先发制人的单处理器系统在 锁,它会永远旋转;没有其他线程能够 获取CPU以释放锁(因为它不能屈服)。 已启用的抢占被优化为不执行任何操作,但 改变IRQ掩蔽状态的那些(在Linux中是 spin_lock_irqsave() ). 因为先发制人,即使你从来没有 如果希望您的代码在SMP系统上运行,您仍然需要实现 正确锁定。

    如果您对可由在中断上下文(硬件或软件)中运行的代码获取的自旋锁感兴趣,则必须使用 spin_lock_* 它会禁用中断。如果不这样做,当您进入关键部分时,中断一出现,系统就会死锁。

        2
  •  6
  •   Eric Seppanen    15 年前

    如果你要用 spin_lock() 在非抢占式内核上,为了保护数据不受中断处理程序的影响,您可能会死锁(在单处理器机器上)。

    如果中断处理程序在其他内核代码持有锁的情况下运行,它将永远旋转,因为常规内核代码无法恢复并释放锁。

    只有当锁夹始终可以运行到完成时,才能使用旋转锁。

    中断处理程序可能需要的锁的解决方案是 spin_lock_irqsave() ,在保持自旋锁时禁用中断。对于1个cpu,没有中断处理程序可以运行,因此不会出现死锁。在smp上,中断处理程序可能会在另一个cpu上开始旋转,但是由于持有锁的cpu不能被中断,因此锁最终会被释放。

        3
  •  6
  •   caf    15 年前

    回答问题的两个部分:

    即使在非抢占式内核上,中断处理程序仍然可以执行,例如。。。

    spin_lock() 不应该防止中断处理程序-仅用户上下文内核代码。 spin_lock_irqsave() 是中断禁用版本 不是吗 非抢占式单处理器上的禁止操作。

    不允许拿着旋转锁睡觉。这是“原子调度”错误。如果你想睡觉,你必须使用一个互斥锁代替(再次-这些不是一个非抢占单处理器上的禁止操作)。

        4
  •  1
  •   nmichaels    15 年前

    根据定义,如果您使用的是非抢占式内核,则不会被抢占。如果你自己做多任务处理,那不是内核的问题;那是你的问题。中断处理程序仍可以执行,但不会导致上下文切换。