【发布时间】: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() 是更好的做法吗?我倾向于后者,原因有两个:
- 一旦有人看到使用
spin_lock_irqsave()获取了锁,很明显该锁是要与中断上下文共享的。 - 作为维护代码的人,您不必确保特定函数是否会在什么上下文中被调用。换句话说,使用
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