第六章 锁

大多数内核,包括xv6,交错执行多个活动。交错的一个来源是多处理器硬件:计算机的多个CPU之间独立执行,如xv6的RISC-V。多个处理器共享物理内存,xv6利用共享(sharing)来维护所有CPU进行读写的数据结构。这种共享增加了一种可能性,即一个CPU读取数据结构,而另一个CPU正在更新它,甚至多个CPU同时更新相同的数据;如果不仔细设计,这种并行访问可能会产生不正确的结果或损坏数据结构。即使在单处理器上,内核也可能在许多线程之间切换CPU,导致它们的执行交错。最后,如果中断发生在错误的时间,设备中断处理程序修改与某些可中断代码相同的数据,可能导致数据损坏。单词并发(concurrency)是指由于多处理器并行、线程切换或中断,多个指令流交错的情况。

内核中充满了并发访问数据(concurrently-accessed data)。例如,两个CPU可以同时调用kalloc,从而从空闲列表的头部弹出。内核设计者希望允许大量的并发,因为这样可通过并行性提高性能,并提高响应能力。然而,结果是,尽管存在这种并发性,内核设计者还是花费了大量的精力来使其正确运行。有许多方法可以得到正确的代码,有些方法比其他方法更容易。以并发下的正确性为目标的策略和支持它们的抽象称为并发控制技术(concurrency control techniques)。

Xv6使用了许多并发控制技术,这取决于不同的情况。本章重点介绍了一种广泛使用的技术:。锁提供了互斥,确保一次只有一个CPU可以持有锁。如果程序员将每个共享数据项关联一个锁,并且代码在使用一个数据项时总是持有相关联的锁,那么该项一次将只被一个CPU使用。在这种情况下,我们说锁保护数据项。尽管锁是一种易于理解的并发控制机制,但锁的缺点是它们会扼杀性能,因为它们会串行化并发操作。

本章的其余部分解释了为什么xv6需要锁,xv6如何实现它们,以及如何使用它们。