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

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.xdnf.cn/news/18082.html

相关文章:

  • 按键序列常用示例
  • Mini MAX AI应用矩阵测评报告——基于旗下多款产品的综合体验与行业价值分析
  • 六大主流负载均衡算法
  • 分享一个基于Hadoop的二手房销售签约数据分析与可视化系统,基于Python可视化的二手房销售数据分析平台
  • Oracle按照特定列值排序和C#统计特定列值的所有行
  • p5.js 3D盒子的基础用法
  • 【解决笔记】MyBatis-Plus 中无 selectList 方法
  • RK3588消费级8K VR一体机 是否有坑?
  • ABP vNext+ WebRTC DataChannel 低延迟传感推送
  • 《JMeter核心技术、性能测试与性能分析》 教学大纲及标准
  • JavaScript性能优化30招
  • Nacos-5--Nacos2.x版本的通信原理
  • C#---StopWatch类
  • 【开源大模型和闭源大模型分别有哪些?两者的对比?部署私有化模型的必要性有哪些?】
  • 五、ZooKeeper、Kafka、Hadoop、HBase、Spark、Flink集群化软件的部署
  • @Autowired @Resource IDE警告 和 依赖注入
  • 代码随想录刷题Day33
  • C#控制台输入(Read()、ReadKey()和ReadLine())
  • 关于simplifyweibo_4_moods数据集的分类问题
  • 企业级Spring事务管理:从单体应用到微服务分布式事务完整方案
  • 【CUDA 编程思想】FusedQKVProj-分组量化矩阵乘法高效实现全流程解析
  • IT资讯 | VMware ESXi高危漏洞影响国内服务器
  • 软考 系统架构设计师系列知识点之杂项集萃(123)
  • 怎样使用数据度量测试
  • Spring 条件注解与 SPI 机制(深度解析)
  • 社区物业HCommunity本地部署手册
  • 51单片机-驱动蜂鸣器模块教程
  • 力扣400:第N位数字
  • 我的学习认知、高效方法与知识积累笔记
  • 【Docker】搭建一个高性能的分布式对象存储服务 - MinIO