5

我最近阅读了 LDDv3 书的第5.5.2节(自旋锁和原子上下文):

持锁时避免睡觉可能会更加困难;许多内核函数可以休眠,而且这种行为并不总是有据可查。将数据复制到用户空间或从用户空间复制数据就是一个明显的例子:在复制可以继续之前,可能需要从磁盘换入所需的用户空间页面,并且该操作显然需要休眠。几乎任何必须分配内存的操作都可以休眠;kmalloc 可以决定放弃处理器,并等待更多内存可用,除非明确告知不要这样做。睡眠可能发生在令人惊讶的地方;编写将在自旋锁下执行的代码需要注意您调用的每个函数

我很清楚,自旋锁必须始终保持尽可能短的时间,而且我认为从头开始编写正确的使用自旋锁的代码相对容易。

然而,假设我们有一个广泛使用自旋锁的大型项目。我们如何确保从受自旋锁保护的关键部分调用的函数永远不会休眠?

提前致谢!

4

2 回答 2

5

为您的内核启用“Sleep-inside-spinlock 检查”怎么样?当您运行 make config 时,通常可以在内核调试下找到它。你也可以尝试在你的代码中复制它的行为。

于 2010-09-09T18:13:11.423 回答
-2

我在很多项目中注意到的一件事是人们似乎滥用了自旋锁,它们被使用而不是其他应该使用的锁定原语。

linux 自旋锁仅存在于多处理器构建中(在单进程构建中,自旋锁预处理器定义为空)自旋锁是多处理器平台上的短期锁。

如果代码未能获得自旋锁,它只会旋转处理器,直到锁空闲。因此,在不同处理器上运行的另一个进程必须释放锁,或者它可能被中断处理程序释放,但等待事件机制是等待中断的更好方法。

irqsave 自旋锁原语是一种禁用/启用中断的简洁方式,因此驱动程序可以锁定中断处理程序,但这应该只保留足够长的时间,以便进程更新与中断处理程序共享的某些变量,如果禁用中断,你是不会被安排。

如果您需要锁定中断处理程序,请使用带有 irqsave 的自旋锁。

对于一般内核锁定,您应该使用互斥锁/信号量 API,如果需要,它将在锁上休眠。

要锁定在其他进程中运行的代码,请使用 muxtex/semaphore 要锁定在中断上下文中运行的代码,请使用 irq save/restore 或 spinlock_irq save/restore

要锁定其他处理器上运行的代码,请使用自旋锁并避免长时间持有锁。

我希望这有帮助

于 2010-09-15T16:17:49.720 回答