# 第 38 章实验:用内存数组模拟 RAID-5 `raid.c` 把 N 块"磁盘"建在内存里(每块盘是 64 个数据块组成的数组),按原书 Figure 38.7 的 **左对称(left-symmetric)** RAID-5 布局放置数据和旋转校验块,然后做三件事: 1. **全条带写(full-stripe write)** 填满阵列:每行 N-1 个数据块一次写完,校验直接由新数据 XOR 得到,不需要任何读。 2. **拔盘 + 重建**:假设磁盘 2 故障(fail-stop),对每一行读其余 N-1 块并 XOR,把磁盘 2 的内容算回来, 再和保存的"原始数据"逐字节比较。 3. **小写(small write)的两种校验更新方法**:对同一组 1000 次随机单块写,分别用 - 减法(subtractive):读旧数据 + 读旧校验,`P_new = (C_old ⊕ C_new) ⊕ P_old`,再写新数据 + 新校验,**固定 4 次 I/O**; - 加法(additive):读同一行其他 N-2 个数据块,与新数据 XOR 得到新校验,再写 2 块,**共 N 次 I/O**; 统计平均每次写的物理 I/O 数,并检查两种方法最后得到的校验块是否完全相同。 ## 怎么跑 ```bash cd labs/38-raid make ./raid # 默认 N=5,块大小 4096 字节 ./raid 3 512 # 3 块盘,512 字节的块 make clean ``` ## 该观察到什么 - `[1]` 行:全条带写每行 N 次写、0 次读——这就是顺序写能拿到 (N-1)·S 带宽的原因。 - `[2]` 行:64/64 个块重建后与原数据完全一致;每重建一个块要读 N-1 次,重建整块盘的读量 = (N-1) × 盘大小。 重建期间阵列没有冗余,再坏一块盘就会丢数据。 - `[3]` 表:加法方法的 I/O 数随 N 线性增长(N 次),减法固定 4 次; **N=3 时加法更省,N=4 时一样多,N≥5 时减法更省**——这就是原书留给读者思考的"交叉点"。 两种方法算出的校验块总是相同,因为 XOR 满足交换律、结合律,且 `x ⊕ x = 0`。 ## 为什么 XOR 校验维持的不变量是:每一行(包括校验块)里每个比特位上 1 的个数为偶数。丢了任意一块, 把剩下的全部 XOR 起来就恰好得到丢失的那块。减法方法利用 `C_old ⊕ C_new` 正好标出"哪些位变了", 把这些位在旧校验上翻转即可,所以不需要读同一行的其他块。