Appearance
完全没有锁
有几个地方 xv6 在完全没有锁的情况下共享可变数据。 一个是在自旋锁的实现中,尽管可以认为 RISC-V 原子指令依赖于硬件中实现的锁。 另一个是 main.c
(kernel/main.c:volatile
) 中的 started
变量,用于防止其他 CPU 在 CPU 0 完成 xv6 初始化之前运行; volatile
确保编译器实际生成加载和存储指令。
Xv6 包含这样的情况:一个 CPU 或线程写入一些数据,而另一个 CPU 或线程读取这些数据,但没有专门用于保护这些数据的特定锁。 例如,在 fork
中,父进程写入子进程的用户内存页,而子进程(一个不同的线程,可能在不同的 CPU 上)读取这些页;没有锁明确保护这些页。 这严格来说不是一个锁问题,因为子进程在父进程完成写入之前不会开始执行。 这是一个潜在的内存排序问题(参见第 5 章),因为没有内存屏障,就没有理由期望一个 CPU 能看到另一个 CPU 的写入。 然而,由于父进程释放锁,并且子进程在启动时获取锁,acquire
和 release
中的内存屏障确保了子进程的 CPU 能看到父进程的写入。