sec*_*red 6 linux synchronization mutex interrupt atomicity
我正在阅读 Linux 信号量的实现。由于原子性,信号和等待(在源代码中向上和向下)使用自旋锁。然后我看到 Linux 在 spin_lock_irqsave 中禁用了中断并在 spin_unlock 中重新启用了中断。这让我很困惑。在我看来,在关键部分禁用中断真的没有意义。
例如,proc A(当前处于活动状态)获取了锁,proc B(阻塞)正在等待锁,proc C 正在做一些不相关的事情。在 A 和 B 之间的临界区内上下文切换到 C 是非常有意义的。即使 C 也尝试获取锁,由于锁已经被 A 锁定,结果将是 C 被阻塞而 A 恢复执行。
因此,我不知道为什么 Linux 决定禁用由自旋锁保护的临界区中的中断。它可能不会导致任何问题,但对我来说似乎是一个多余的操作。
请允许我首先声明我不是 Linux 专家,所以我的回答可能不是最准确的。请指出您可能发现的任何缺陷和问题。
想象一下,如果内核的各个部分使用某些共享数据,包括需要快速且不能阻塞的中断处理程序等操作。假设系统调用foo当前处于活动状态并且已获取锁以使用/访问共享数据bar,并且在获取所述锁时/之前不会禁用中断。
现在一个(硬件)中断处理程序,例如键盘,启动并需要访问bar(硬件中断比系统调用具有更高的优先级)。由于bar当前被 syscall 锁定foo,因此中断处理程序无法执行任何操作。中断处理程序确实需要快速且不会被阻塞,因此它们只是在尝试获取锁时保持旋转,这将导致死锁(即系统冻结),因为 syscallfoo永远没有机会完成并释放其锁。
但是,如果您在尝试获取 中的锁定之前禁用中断foo,那么foo将能够完成它正在执行的任何操作并最终释放锁定(并恢复中断)。任何试图在foo持有自旋锁时进入的中断都将留在队列中,并且能够在锁被释放时启动。这样,您就不会遇到上述问题。但是,还必须注意确保锁定的bar时间尽可能短,以便其他更高优先级的操作可以在需要时接管。
| 归档时间: |
|
| 查看次数: |
3438 次 |
| 最近记录: |