【问题标题】:spin_lock_irqsave() in interrupt context中断上下文中的 spin_lock_irqsave()
【发布时间】:2022-03-24 09:31:55
【问题描述】:

我正在维护一个驱动程序,它在 ISR(即,在中断上下文中)和 read() 系统调用之间共享一些资源。在这两种情况下,都使用了spin_lock_irqsave(),因为(显然)可以在中断上下文中获取资源。

但是,我想知道在中断上下文中是否需要使用spin_lock_irqsave()。即,不可靠的锁定指南(参见此处:https://kernel.readthedocs.io/en/sphinx-samples/kernel-locking.html)指出:

请注意,spin_lock_irqsave() 将在中断打开时关闭它们,否则什么也不做(如果我们已经在中断处理程序中),因此这些函数可以安全地从任何上下文调用。

因此,在中断处理程序中使用“正常”spin_lock()(因为特定的中断已被禁用)然后在用户上下文中调用spin_lock_irqsave(),这是一种常见的做法吗?或者,在任何地方都使用spin_lock_irqsave() 是更好的做法吗?我倾向于后者,原因有两个:

  1. 一旦有人看到使用spin_lock_irqsave() 获取了锁,很明显该锁是要与中断上下文共享的。
  2. 作为维护代码的人,您不必确保特定函数是否会在什么上下文中被调用。换句话说,使用 spin_lock_irqsave() 可以在任何上下文中使用,因此您不必确保仅在特定上下文中调用函数。

如上所述,我想知道对于驻留在内核空间中的代码的约定/最佳实践是什么。即使您可以保证从中断上下文中获取锁,在任何获取锁的地方都使用spin_lock_irqsave() 是否更好?

【问题讨论】:

  • 在中断上下文中使用spin_lock 代替spin_lock_irqsave 是安全的。但是,这样做可能在重用代码时遇到问题:使用非 irq 版本的自旋锁的代码不能在正常(非中断)上下文中使用。如果您不打算在其他地方重用您的 ISR 代码,spin_lock 可以。
  • spin_lock 基本上只会防止重新进入 IRQ 处理程序的部分。系统中的另一个 CPU 可能同时触及 IRQ 上下文之外的相同日期,并且可能会触发 IRQ。如果你在其他一些函数中使用非 irq 版本的自旋锁,数据损坏是有保证的。

标签: c linux-kernel linux-device-driver


【解决方案1】:

请参阅内核文档中的Unreliable Guide To Locking。有一个table of minimum requirements for locking可以在不同的上下文之间进行同步,大致可以概括为:

  1. 如果其中一个是进程:使用足够强大的进程来禁用另一个。例如,如果另一个竞争对手是一个软中断,那么你需要在 至少spin_lock_bh,它在锁定时禁用softirq。
  2. 如果其中一个是硬 irq:硬 irq 的出现是不可避免的,除非你事先禁用它,所以 spin_lock_irqspin_lock_irqsave,取决于另一个是否是硬 irq。
  3. 否则,请使用spin_lock

(当然,这些都是假设您的内核没有配置为PREEMPT_RT

【讨论】:

    猜你喜欢
    • 2020-12-07
    • 2018-04-14
    • 2020-01-19
    • 2011-02-03
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    相关资源
    最近更新 更多