spin_lock_bh()是如何工作的?

6

我正在处理一个设备驱动程序,它在中断服务程序(ISR)和read()调用之间共享资源。

ISR仅调用schedule_work()函数,以便让底半部分来完成繁重的工作。该资源在read()(即用户上下文)和实现底半部分的函数之间进行共享,这就是为什么我要使用spin_lock_bh()进行锁定。

我不理解锁定机制。假设当前有人持有锁,当ISR调用schedule_work()时会发生什么(即在持有锁时触发硬件中断)?任务是否仍然会被调度并在以后的时间运行,还是被丢弃了?换句话说......实际上"锁定"或防止什么(即工作队列还是执行工作)?工作队列是否会更新?

与我的问题相反,如果我使用spin_lock_irqsave(),则在持有锁时ISR将被禁用,因此我一开始就无法执行schedule_work()。但是考虑到资源是共享的,我认为没有必要也不想在持有锁时禁用硬件中断。

2个回答

6

如果一个中断服务程序等待一个锁,而该锁可能被未禁止中断的代码持有,则会导致死锁。 spin_lock_irqsave 首先禁用中断并保存先前状态,然后获取锁定。还原按相反顺序完成此操作。

底半部仍然是中断。 通过禁用底半部执行,spin_lock_bh 执行相当于获取锁定。 这可以防止底半部执行干扰我们的read代码。

锁定防止多个线程执行锁定的代码。 工作队列受到保护,仅在持有锁时操作。


抱歉,我的问题是关于spin_lock_bh()以及当ISR触发schedule_work()来调度底半部分运行时它是如何工作的。 - It'sPete
更新以解释bh。 - stark
感谢您更新的答案。只是为了我自己的清晰度...所以只有底半部分的执行被阻止,但不是调度?这就是我认为事情应该运作的方式,这样您就可以稍后(在释放锁之后)运行底半部分多少次,以完全服务可能在持有锁时出现的任何硬件中断。 - It'sPete
底部一半在锁定期间不会运行,但如果在保持锁定时已安排,则我相信它将在释放锁定后立即运行。https://elixir.bootlin.com/linux/latest/source/kernel/softirq.c#L159 - stark

2

spin_lock_bh禁用软中断(bh是一个古老的术语,实际上是指软中断)。但是,通过schedule_work触发的工作队列实际上并不在softirq中运行,而是在专用线程中运行,因此处于进程上下文。

因此,您的驱动程序只需要简单的spin_lock()来保护免受并发read()调用的影响。

当访问与“top-half”共享的资源时,可能需要禁用中断,但这不是您问题的范围。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接