有些数据只配活在内存里:编译的临时产物、压测时反复读写的高速缓存、不想磨损 SSD 的碎文件。这类需求不用装第三方工具,Linux 内核自带的 brd 模块一条 modprobe 就能凭空造出一块”磁盘”,读写速度就是内存带宽。

诚实边界:brd 是内核模块,容器环境无法加载宿主内核,本文流程未实跑,命令来自原文并对照内核文档(Documentation/admin-guide/blockdev/ramdisk.rst)与 systemd 文档;CentOS 7/8/9、Rocky Linux 通用。

核心机制一句话

brd(block device in RAM)在内核里把一块内存区域包装成标准块设备:你拿到的是真正的 /dev/ramN 设备节点,可以分区、可以 mkfs 任意文件系统——这是它与 tmpfs 最大的不同。

创建内存盘

加载 brd 模块,参数直接跟在后面:

1
modprobe brd rd_nr=1 rd_size=16777216 max_part=0

三个参数:rd_nr 是要几块盘,这里 1 块;rd_size 是单块盘大小,单位 KB,16777216 KB 正好 16GB;max_part=0 表示不启用分区支持,整块盘直接用。

加载成功后,/dev 下就多出了 ram0 这块盘,可以确认一下:

1
lsblk /dev/ram0

验证点:lsblk 能看到 ram0 且 SIZE 列与 rd_size 一致(16G),模块才算加载成功。想压一压速度,dd if=/dev/zero of=/data/test bs=1M count=1024 oflag=direct 写 1GB 看吞吐,结果由机器内存带宽决定。

格式化并挂载

内存盘也要走普通磁盘的流程。先格式化成 ext4:

1
mkfs.ext4 /dev/ram0

然后挂到目录上(挂载点目录要事先存在):

1
2
mkdir -p /data
mount /dev/ram0 /data

此后所有写入 /data 的数据都落在内存里,断电即失——这正是用它的目的,也是它的代价。

用完卸载

不用了就按顺序收掉:卸载文件系统,再把内核模块移除:

1
2
umount /data
modprobe -r brd

modprobe -r 会把 brd 从内核里卸掉,盘上数据随之清空。跳过 umount 直接 -r 时模块会因占用而卸不掉,这个顺序不能反。

开机自动创建并挂载

modprobe 的效果重启就没了。开机自动化要解决两个独立的问题:谁来加载模块、谁来格式化挂载——缺一不可。

加载模块交给 systemd 的 modules-load.d 机制,参数固化在 modprobe 配置里:

1
2
echo "brd" > /etc/modules-load.d/memdisk.conf
echo "options brd rd_nr=1 rd_size=16777216 max_part=0" >> /etc/modprobe.d/memdisk.conf

注:只写 /etc/modprobe.d 的 options 行并不会触发加载——它只定义”加载时带什么参数”,得由 modules-load.d(systemd-modules-load 服务,开机自动读取)负责把 brd 拉起来,两者配套才完整。来源:systemd-modules-load.service(8) 与 modprobe.d(5)。

格式化和挂载交给 rc.local——内存盘每次起来都是空的,mkfs 和 mount 都得重来:

1
2
3
echo "mkfs.ext4 /dev/ram0" >> /etc/rc.d/rc.local
echo "mount /dev/ram0 /data" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local

验证自启是否真的生效:重启一次,开机后 lsblk /dev/ram0 有设备、df -h /data 挂载在位,才算闭环。更现代的替代是把后两行写成一个 oneshot systemd unit,语义比 rc.local 清晰,机器多时也更好统一管理。

brd 还是 tmpfs:选错了白忙

同样是内存存储,两者语义不同,先对齐一眼:

brd tmpfs
形态 块设备 /dev/ramN 文件系统,挂载即目录
文件系统 任意(ext4/xfs…可自选) 固定是 tmpfs 自身
分区/分区表 支持(max_part>0) 不适用
典型用途 应用坚持要 /dev 设备、特定 FS 编译缓存、会话文件

tmpfs 一条 mount -t tmpfs -o size=4G tmpfs /mnt 直接可用,访问路径就是目录,大多数场景它最省事。brd 的价值在块设备语义:某些数据库、测试工具坚持要一个 /dev/ 设备,或者需要 mkfs 成特定文件系统(如 xfs),tmpfs 给不了,brd 补位。反过来,只是想给编译提提速,用 tmpfs 就够了,绕道 brd 属于多余动作。

常见报错

  • modprobe: FATAL: Module brd not found:当前内核没带 brd 模块(部分云镜像、精简内核)。先 ls /lib/modules/$(uname -r)/kernel/drivers/block/ 确认有无 brd.ko,没有就得换内核或改用 tmpfs 方案。
  • modprobe: ERROR: could not insert 'brd': Operation not permitted:在容器里跑的典型报错——容器共享宿主内核且无模块加载权限,brd 这类内核模块方案只能在真机/虚拟机上做。
  • 重启后 /data 没挂上:按”modules-load.d 是否存在、rc.local 是否有执行位、rc-local 服务是否 active”三步查,绝大多数是第三步——新版发行版默认不启用 rc.local,systemctl status rc-local 看一眼便知。

注意事项

  • 内存盘没有任何持久性,只放可再生的临时数据,重要文件别往里放。
  • 盘吃的是真实物理内存:rd_size 给多大,写满就要占多大,按实际需要定,别拍脑袋开大。
  • 挂载点目录要先建好,mount 不会替你 mkdir。
  • umount 之前模块卸不掉;反过来 reboot 会连数据带设备一起清空,依赖盘上数据的脚本要做好”每次都是空盘”的假设。

小结

回到开头的场景:编译产物、压测缓存这些”用完即弃”的数据,brd 一条 modprobe 就能给一块内存带宽的块设备。记住四件事——数据不持久、容量就是内存、开机自启要 modules-load.d 与 rc.local 配套、和 tmpfs 的分工是”块设备语义 vs 目录即用”——它就是一台随取随用的临时高速盘。


本文由作者 2020-2024 年间的 CSDN 博客文章重构而来,原发布于 CSDN。