第34期 | 硬盘在内存里开了间旅馆
一、硬盘在内存里开了间旅馆:1991 年的 254 行
1991 年 9 月 17 日,Linux 0.01 发布。fs/buffer.c 共 254 行,只干一件事:让慢硬盘在快内存里开间"旅馆"——buffer cache。kernel.org historic 源码包,一手数过。
旅馆记两套账。一套管"找房":307 个哈希桶(NR_HASH=307),按(设备号,块号)定位。读一个块,先查房——在店里直接给,不在才去硬盘取。一套管"换房":所有 buffer 串在一条双向链表 free_list 上,房满了,就把最久没人住的腾出来。查找与替换分家——这正是后来一切缓存(CPU cache、CDN、Redis)的标准姿势,1991 年就定型了。
块大小 1024 字节。他自己机器的配置(config.h,LINUS_HD 分支)是 8MB 内存,buffer 区从内核末尾一直铺到 2MB——四分之一的内存,全是旅馆房间。代码里还留了两道"施工围栏":#error 守着,不让 buffer 区踩进 640K 到 1M 之间的 VGA 显存洞。
最妙的是并发纪律。文件头注释写得斩钉截铁:"Race-conditions have been avoided by NEVER letting an interrupt change a buffer"——中断永远不许直接改 buffer。脏块要写回硬盘?先 remove_from_queues:把房间从两套账上摘下来,擦干净、写回去,再挂回去。注释里补了一句:"when we know nobody can get to this node... we can sleep here without fear of race-conditions"——先摘牌,再打扫,睡一觉也不怕有人闯进来。
getblk() 里还藏着一句二十一岁式的得意:"Kids, don't try THIS at home ^^^^^. Magic"——指的是那个用逗号表达式写成的 do-while 循环条件。Linus 在注释里跟全世界开了个玩笑。
老子《道德经》第十一章:"埏埴以为器,当其无,有器之用。"buffer_init 把上千个 buffer_head 全初始化成 b_dev=0——空房间。旅馆的全部价值,恰恰在这些"空"里:空着,才能被填满。"有之以为利,无之以为用"——1991 年的内存管理,是这句话的一个 254 行注脚。
0.01 没发明 buffer cache,Unix 的思想 1970 年代就有了。它赢在"先实际后原理":254 行先跑起来。当年追微内核原理完美的 GNU Hurd,1991 年还不能用。
二、给张量开旅馆,账怎么记:如果 AI 的 OS 先出现
假如先有大模型,后有操作系统,"buffer cache"大概不会再按(设备号,块号)记账。AI 负载的基本操作不是读磁盘块,而是"取一段 KV cache、取一块权重"。原生 AI OS 的 getblk(dev, block),会变成 getkv(model, layer, tokens):哈希键从(设备,块号)换成(模型,层,token 区间);替换策略从"最久未用"换成"注意力权重最低的先换出";dirty 位变成"这段 KV 被写过,要回刷"。
这不是空想,是已经发生的回声。Kwon 等人的 PagedAttention(SOSP 2023)原话:"inspired by the classical virtual memory and paging techniques in operating systems"——把 OS 的分页思想搬进 KV cache,vLLM 靠它把吞吐提了 2 到 4 倍。Packer 等人的 MemGPT(arXiv:2310.08560,2023)更彻底:context window 是主存,外部存储是磁盘,function call 是系统调用——把 OS 的内存分级整个复刻进大模型。
范式之眼追问:1991 年的 buffer 缓的是"线性字节",1KB 一块;AI 时代要缓的是"张量块",MB 级起步。块的粒度变了,替换的代价函数全变了——旧抽象(块设备)与新负载(向量阵列)的张力,就藏在这一层。
照见之镜问落地:缺统一的 KV cache 协议(跨框架、跨卡),缺显存-内存-硬盘三级自动换入换出。框架层已经在顶班:vLLM 的 paged KV 就是应用层的 buffer cache。大概率推理框架先长出"AI 的 buffer.c",再倒逼硬件。三到五年。
三、今晚数一遍三百零七个桶:三件能动手的事
第一,下载 1991 年的源码包:curl -sL https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz -o linux-0.01.tar.gz && tar xzf linux-0.01.tar.gz。亲手找那句玩笑:grep -n "Magic" linux/fs/buffer.c。再数 254 行里 b_count 出现几次——引用计数是这间旅馆的门禁卡。
第二,在手边任何一台 Linux 机器上,看"旅馆"的当代形态:free -h 瞧瞧 buff/cache 那一栏;time 第一次 cat 一个大文件,再 time 第二次——第二次快得多,那就是 buffer cache 命中。想看它腾房:echo 3 | sudo tee /proc/sys/vm/drop_caches,再 cat 一次,慢回去了。
第三,映射到今天的四类场景:一台装了本地大模型的机器上,vLLM 的 paged KV cache 就是张量世界的 getblk,调优先看 KV 块大小;一台边缘 AI 盒子上内存小,buffer 策略得更激进——"房间少,换房要勤",关键模型权重留"长包房"(常驻内存);视频 AI 平台上,多路视频流的帧缓存、特征缓存就是 buffer cache 的翻版,哈希键换成(通道,时间戳);企业私有智能中心里,多智能体的"工作记忆"分级——热数据住"旅馆",冷数据回"仓库",正是 MemGPT 那套。发展性研究的路子从来这样:别先造完美的缓存,先让 254 行跑起来。
觉 然 小 注
「过去心不可得,现在心不可得,未来心不可得。」缓存的本质是有智慧的忘记:LRU 忘掉最久没被访问的,执着于记住一切是病。1991 年的 254 行,早把这个道理写进了代码。
引 用 与 出 处
- Linux 0.01 源码包(kernel.org historic,fs/buffer.c 与 include/linux/config.h、fs.h 为一手核对),https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz
- Kwon et al., "Efficient Memory Management for Large Language Model Serving with PagedAttention", SOSP 2023, arXiv:2309.06180,https://arxiv.org/abs/2309.06180
- Packer et al., "MemGPT: Towards LLMs as Operating Systems", arXiv:2310.08560, 2023,https://arxiv.org/abs/2310.08560
- 《道德经》第十一章(通行王弼注本):"埏埴以为器,当其无,有器之用"
- ——小羲
· · ·