# 第 50 章实验:AFS 缓存一致性模拟器 `afs_sim.c` 是一个单进程、输出确定的小型模拟器,逻辑与网页上的"AFS 缓存一致性时间线"模拟器相同: 整文件缓存、回调(callback)、close 时 Store 并打断其他客户端的回调、本机进程立即看到写、最后关闭者胜。 ## 编译与运行 ```bash cd labs/50-afs make ./afs_sim # 两部分都运行 ./afs_sim 1 # 只运行 Figure 50.3 ./afs_sim 2 # 只运行交错枚举 ``` ## 应该观察到什么 1. **第 1 部分:原书 Figure 50.3 逐行复现。** 输出的 27 行与书中表格一致: - 第 10 行 P2 读到 B:同一台机器上的进程立刻看到 P1 未关闭的写; - 第 13 行 P3 读到 A:另一台机器要等 P1 close; - 第 15 行 P1 close 后 Client2 的缓存变成 `~A`(回调被打断,对应书中划掉的 A); - 第 26 行 P3 读到 D:P1 最后关闭,"最后写者胜"。 最后一行统计消息:4 次 Fetch、4 次 Store、3 次回调中断,没有任何 TestAuth。 2. **第 2 部分:交错枚举。** 两个客户端各执行 3 步,共 C(6,3)=20 种调度(`0` 表示 client0 走一步, `1` 表示 client1 走一步,与 `afs.py -S` 的记法相同)。 - 工作负载 1(一写一读):AFS 下只有 `000111` 读到 1(close 必须早于对方的 open); NFS(属性缓存超时 T=0)下有 4 种(close 早于对方的 read 即可)。 - 工作负载 2(两个都写):结果只取决于最后一个 close 是谁——调度以 0 结尾则 X 胜,否则 Y 胜,各 10 种。 ## 可以尝试 - 修改 `part1()` 中的 `fig[]` 数组,构造自己的操作序列(`{进程号 0~3, 操作, 值}`,进程 0、1 在 Client1,2、3 在 Client2)。 - 加入 `{0,DOWN,0}` / `{0,UP,0}`(这里 proc 字段表示客户端号)或 `{0,SCRASH,0}`, 再把 `SUSPECT_ON_RECOVER` 改成 0,观察客户端错过回调中断、或服务器丢失回调表后读到陈旧数据。