C++ / a working model

147 / 163   ·   C11   ·   约 8 分钟

日志结构文件系统

先记住这句话

日志结构文件系统通过内存缓冲全部更新(含元数据)并以大段顺序写入空闲磁盘区域,应对缓存增大后的写主导流量,逼近峰值带宽并缓解RAID小写惩罚。

本篇内容
  1. LFS诞生的驱动力
  2. 用内存段把写入变成高效顺序流
  3. 该缓冲多大才划算
  4. 运行示例
  5. 动手练习

官方章节 PDF

LFS诞生的驱动力

内存变大后读大多由缓存完成,磁盘几乎只剩写流量。硬盘密度提升让顺序带宽猛增,但机械寻道与旋转改善缓慢,随机访问落后。传统文件系统创建小文件时对inode、位图、目录多次小写,即使同组也产生短寻道。RAID-4/5的小写更会放大成四次物理I/O。LFS把所有更新变成大顺序写来解决这些问题。

用内存段把写入变成高效顺序流

仅按连续地址写仍会因两次写之间的旋转而浪费时间。LFS先把数据和inode等元数据全部积在内存段里,段满后一次性顺序写到磁盘空闲处,从不原地覆盖。段足够大就能摊销定位开销,让有效带宽接近峰值。数据与元数据同段共存,保证一次传输完成全部相关更新。

该缓冲多大才划算

缓冲量由定位开销T_position相对峰值速率R_peak决定。要让有效速率达到峰值的F倍,所需数据量D满足D = [F/(1-F)] × R_peak × T_position。段越大,机械延迟被隐藏得越好,越接近顺序传输极限。

常见误区

  • 以为只要地址连续就能达到峰值,忽略必须一次发出足够大的连续传输。
  • 只缓冲数据块而把inode和位图仍随机写回原地。
  • 误认为读取也会自动变成顺序,其实LFS只优化写路径。

运行一个例子

最低标准 C11 · 完整程序 · 下载 .c

#include <stdio.h>

int main(void) {
    double t_pos = 0.01;
    double r_peak = 100.0;
    double f = 0.9;
    double d = (f / (1.0 - f)) * r_peak * t_pos;
    printf("Needed buffer: %.1f MB\n", d);
    return 0;
}

在本地编译

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-43-lfs.c -o example && ./example

预期结果

Needed buffer: 9.0 MB

CHECK YOUR UNDERSTANDING

合上答案,试着解释。

定位时间8 ms、峰值速率50 MB/s、目标90%峰值带宽时,LFS应缓冲多少MB?

查看参考答案

F=0.9则F/(1-F)=9,D=9×50×0.008=3.6 MB。

继续查证

标准草案与官方章节会更新;版本标记只说明示例最低要求。

回到目录