当前位置: 首页 > news >正文

ramdisk内存虚拟盘(一)——前世今生

1990 年代:前因——“硬盘太慢、驱动太多”

  • 背景:早期 Linux 根文件系统要么在软盘、要么在 IDE 硬盘,内核把对应的软盘/IDE 驱动编进去即可顺利挂载。
  • 矛盾出现:随着 SCSI、PCMCIA、USB、RAID 控制器等百花齐放,如果把所有可能的驱动都静态编进内核,内核体积会爆炸;如果把驱动当模块放在 /lib/modules,又陷入“挂载根文件系统需要根文件系统里的模块”的鸡与蛋问题。
  • 解决思路:在内存里先伪造出一个“小硬盘”(ramdisk),把必备驱动、工具、甚至 fsck 都塞进这个内存盘;内核只要能识别内存本身,就能先挂 ramdisk,再从 ramdisk 里加载真正的存储驱动,最后 pivot 到真正的根文件系统
    这就是 ramdisk 技术诞生的直接原因——启动阶段的“驱动跳板”

1995:首次实现——rd.c 与 ramdisk 的诞生

  • 1995 年左右的内核 1.x/2.0,出现了最早的 rd.c;它把一段连续的物理内存注册成块设备 /dev/ramX,再通过 mke2fs 格式化就能当磁盘用
  • 特点:
    – 大小在编译时固定(默认 4 MB,最多 16 个设备);
    – 需要完整走块设备层,先格式化再挂载,浪费内存和 CPU;
    – 掉电即失,只能放启动时一次性数据 。

1999-2002:initrd 标准化——压缩 cramfs/ext2 镜像

  • 为了解决早期 ramdisk 浪费内存的问题,社区把 ramdisk 做成压缩镜像(ext2、cramfs、romfs),由 bootloader 一次性读入内存,内核解压后挂载为临时根文件系统
  • 这就是我们今天说的 initrd(initial ramdisk)。
  • 启动流程变为:
    1. bootloader 把内核 + initrd.gz 读进内存;
    2. 内核启动→解压 initrd→挂载为 /→执行 /linuxrc 或 /init
    3. /init 加载 udev、驱动、建立 /dev 节点→挂载真正的根文件系统→switch_root
  • 局限性:镜像大小固定,需要事先估算;解压后仍占用整块内存;脚本维护复杂。

2004-2006:initramfs 兴起——ramfs/tmpfs 取代块设备

  • 内核 2.4/2.6 引入 initramfs技术上基于 ramfs/tmpfs,而非块设备
  • 区别:
    不再是块设备,而是直接利用 page cache 当文件系统,省掉一次格式化/缓存复制;
    大小可变,按需增长,可回收;
    – 使用 cpio 格式打包,可无缝嵌入内核镜像(CONFIG_INITRAMFS_SOURCE);
    – 启动脚本统一为 /init,接口更简单 。
  • 结果:initrd 退出主流,initramfs 成为各大发行版的默认启动机制。

2007-至今:brd 模块、tmpfs 日常化

  • 传统 ramdisk 块设备演化为 brd(block ramdisk,drivers/block/brd.c),仍保留在源码,用于:
    – 无盘机、嵌入式系统需要真正“磁盘”语义的场景;
    – 测试块层、文件系统完整性校验等。
  • 日常使用中,tmpfs 全面接管“内存当磁盘”的需求:
    – /tmp、/run、/dev/shm 默认挂载 tmpfs;
    – 读写速度 1 GB/s 以上,空间随用随还;
    – 不再掉坑“固定大小、双份缓存” 。

副作用与经验教训

  • 掉电即失:曾有人把 MySQL 数据目录放在 ramdisk 以求极速,结果断电订单归零 。
  • 内存是昂贵资源:ramdisk 占用不可回收的连续内存,tmpfs 则可用 swap、可回收,性价比更高。
  • 安全场景:ramdisk 的易失性反而成为“解密后即焚”的理想场所,例如高安全级别下的临时解密盘 。

一句话总结
ramdisk 最初是“为了启动而伪造的磁盘”,后来变成“为了速度而牺牲容量”的利器,最终被 initramfs + tmpfs 取代——它完成了“启动跳板”的使命,也留给我们一条宝贵经验:内存不是保险箱,速度和安全必须权衡。

http://www.lryc.cn/news/622484.html

相关文章:

  • Python爬取推特(X)的各种数据
  • 功能组和功能组状态的概念关系和区别
  • 【揭秘红黑树:高效数据结构解析】
  • 谈谈《More Effective C++》的条款30:代理类
  • JavaScript 防抖(Debounce)与节流(Throttle)
  • Python入门第2课:变量、数据类型与输入输出
  • MySQL(多表查询练习)
  • C#控制台输入(Read()、ReadKey()和ReadLine())
  • 【大模型微调系列-01】 入门与环境准备
  • Linux信号保存
  • PowerShell 格式化系统完全掌握(上):工作原理、默认规则与三大格式化命令
  • 【数据分享】上市公司创新韧性数据(2007-2023)
  • 数据处理分析环境搭建+Numpy使用教程
  • MySQL、PolarDB、PolarDB-X、TableStore、MongoDB、TiDB、ClickHouse选型
  • CIAIE 2025上海汽车内外饰展观察:从美学到功能的产业跃迁
  • 中级统计师-会计学基础知识-第一章 账户与复试记账
  • imx6ull-驱动开发篇25——Linux 中断上半部/下半部
  • 嵌入式学习 day52 IMX6ULL裸机开发-I2C
  • Redis核心应用场景及代码案例
  • WordPress 7B2主题,在使用PHP 8.0+出现502的解决办法。
  • 【机器学习深度学习】OpenCompass 评测指标全解析:让大模型评估更科学
  • platform总线注册流程分析
  • 洛谷 P2842 纸币问题 1 -普及-
  • C++类与对象核心知识点全解析(下)
  • 模板方法模式C++
  • 机器翻译:模型微调(Fine-tuning)与调优详解
  • JavaWeb开发_Day13
  • vue3相关基础
  • MySQL知识解析
  • linux-----------------锁