一种实现嵌入式Linux的新方法-ramdisk(2007年发表)

2019-07-13 06:39发布

  引言

在Linux操作系统中,有一项特殊的功能——初始化内存盘INITRD(INITial Ram
Disk)技术,而且内核支持压缩的文件系统映像。有了这两项功能,我们可以让Linux系统从小的初始化内存盘启动,并把系统内存的一部分作为根文件系
统挂载,而且不使用交换分区(如果不运行X
Windows这是完全可以的),即把Linux系统完全嵌入到内存中,而不依赖于任何其他硬盘。现在PC机内存至少128M,而根文件系统所用的只有
30M,因此不仅不会使整机性能下降,反而有很大的提高。


由于系统不工作在硬盘上,所以系统消除了由于机械驱动而导致的问题;因为系统运行于内存中,根文件系统和操作完全在CPU/RAM环境下,系统性能在速度
和可靠性方面非常好;它不会由于非法关机而破坏文件系统,因为我们每一次启动是把压缩的文件系统解压至内存盘中作为根文件系统挂载。


              1 硬件要求


对于这样一个系统,硬件不需要特别的设计,只是通过普通的PC机上的组件实现。值得一提是系统的内存的大小,它至少应该有64M。因为30M作为
Ramdisk使用,剩下30多兆作为系统运行,才能保证系统的正常工作,我们现在的计算机内存一般为128M,这个条件都能满足。
唯一特别的是一个
flash盘 ,它相当于一个IDE接口的硬盘,大小为20M,主要用它作为启动LILO和放置根文件系统压缩包。


              2 Ramdisk的使用


Ramdisk就是将内存的一部分分配为一个分区并作为硬盘来使用。对于系统运行时不断使用的程序,将它们放在Ramdisk中将加快计算机的操作,如大
数据量的网络服务器、无盘工作站等。为了能够使用Ramdisk,我们在编译内核时须将block
device中的Ramdisk支持选上,它下面还有两个选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。它既可
以直接编译进内核,也可以编译成模块,在需要的时候加载。我们由于在启动时就用它,所以必须将它直接编译进内核。


              如果对Ramdisk的支持已经编译进内核,我们就可以使用它了。
首先在/mnt目录下创建目录ram,运行mkdir /mnt/ram;然后对/dev/ram0创建文件系统,运行mke2fs
              /dev/ram;最后挂载上/dev/ram,运行mount /dev/ram /mnt/ram,就可以象对普通硬盘一样对它进行操作了。
值得注意的是,在创建文件系统的时候,在屏幕上输出1024
              inodes ,4096 blocks,即ramdisk大小为4M=4096个块,但是我们挂载上之后,用命令df –k /dev/ram查看时,显示出来ramdisk大小只有3963K,这是由于文件系统本身占用了一些空间。



我们能根据需要改变ramdisk地大小。如我们要把默认的4M增大到10M,当ramdisk是直接编译进内核的情况下,可在LILO配置文件
lilo.conf中加入一行:append=“ramdis_size=10000”,运行LILO后,重启计算机后,ramdisk大小变为10M,
或者在启动是作为启动行参数ramdis_size=10000;当ramdisk是作为可加载模块编译时,需要在模块加载配置文件
/etc/modules.conf中加入一行:options rd
rd_size=10000,或者在加载rd模块是在后面加上说明,即insmod rd rd_size=10000.


              3 实现过程



              3.1创建压缩的文件系统



我们的实现过程是依赖于存在的Linux系统。首先启动一般的Linux系统,在这个系统中根据自己的需要,创建一个适合功能的文件系统。例如我们要实现
Apache网络服务器,那么只要把完成系统启动和基本维护需要的一些命令、脚本、配置文件和库函数留下,再加上实现Apache服务器所需要的。具体过
程为:


在Linux下建立目录/minlinux,我们在此目录下创建的文件系统。
系统的所有静态链接库,帮助手册(man pages),信息页(info
pages),头文件,内核源码对于系统运行是完全无用的,所以不需要它们。在目录bin下放系统维护的一些基本工具,如ls、mv、grep、
chown、chmod、chgrp、ln、rm等;在sbin下是系统启动过程通常需要的命令,如bash、e2fsck、mke2fs、fdisk、
insmod、rmmod、depmod、modprobe、lsmod、shutdown、reboot、login、init、getty、
mount、umount、等;usr/bin下放置Apache应用程序http和其他一些特殊工具。然后根据这些可执行文件需要的动态链接库来确定
lib目录下的内容。当然目录etc下的配置文件,dev下的设备文件需要的都必须要有,它们都是和可执行文件对应的,因为许多可执行文件执行时,一般是
打开设备,根据配置文件来运行。有一个特殊的目录proc应该设置,在内核编译选项文件系统选择中,我们选择对文件系统proc的支持,那么在系统运行之
后它下面有许多内容,这些内容是实时、不断跟踪系统内核和正在运行的进程的状态而产生的,但不占用任何磁盘空间,而是驻留在内存中。在某些情况下,可以通
过它来系统设置,许多工具从这里获取信息,如dmesg、ps、top等。


              文件系统制作完成,大小应该在20M左右。



              接下来把文件系统拷贝至ramdisk为生成ramdisk映像文件做准备。我们把系统的ramdisk 改变到30M,重启计算机后,执行下列操作:


              dd if=/dev/zero of=/dev/ram bs=1k count=30000
把ramdisk调整到零,以便后面有更高的压缩率;


              mke2fs –m0 /dev/ram 30000
在ramdisk上建立30M的ext2文件系统;


              mount /dev/ram /mnt/ram
将已格式化的ramdisk挂载至目录/mnt/ram;


              cp –av /minlinux/* /mnt/ram
将文件结构拷贝至ramdisk。


然后我们对/mnt/ram/etc目录下的文件进行修改。主要的文件是fstab,它负责在系统启动时把系统要挂载的文件系统信息传递给启动进程,我们
使用ramdisk作为根文件系统,且不需要交换分区,所以此文件配置为

/dev/ram / ext2 defaults 1 1


              none /proc proc defaults 0 0



              即可。一般来说系统启动时都要激活交换分区,即在启动脚本中有swapon –a 命令,但我们不需要交换分区,因此要把这一项移除,否则启动时会打印错误信息然后停止启动。


              最后我们要拷贝ramdisk的映像并将其压缩。主要步骤如下:


              运行df ,注意1024-blocks一栏中/dev/ram的数值,在我的机上为25600;



              卸载/dev/ram,运行cd /root切换至root目录并运行umount /dev/ram;


              将ramdisk写成映象文件,运行dd if=/dev/ram of=ram30.img bs=1k count=25600


              压缩,并在/root目录下产生一个压缩的映象文件ram30.img.gz,

运行
gzip –9v ram30.img




              3.2创建initrd ramdisk 映像



              首先我们在/dev/ram0中创建一个适合大小的ext2文件系统,方法同上,只是大小只有2048K,因为initrd ramdisk是用来引导(bootstrap)30M的ramdisk,并将它挂载至/mnt/ram


              然后在/dev/ram0中建立映像需要的目录和文件。创建目录bin、dev、etc、lib、mnt和可执行脚本文件linuxrc,linuxrc的内容为:


              #!/bin/bash



              mount –o –ro /dev/hda1/ /mnt
# 以只读方式将flash盘挂载在/mnt下


              zcat /mnt/boot/ram30.img.gz > /dev/ram
# 将根文件系统映像解压至ram


              umount /dev/hda1
# 卸载flash盘

*************


              #!/bin/bash




              mount –o –ro /dev/hda1/ /boot
# 以只读方式将/dev/hda1/盘挂载在/boot



              zcat ram30.img.gz > /dev/ram
# 将根文件系统映像解压至ram



              umount /dev/hda1
# 卸载flash盘


bin下面为linuxrc中用到的命令;lib为这些命令需要的动态链接库;etc下为配置文件ld.so.conf,定义命令运行时寻找所需动态链接
库的路径,运行命令ldconfig –r
/mnt/ram产生文件ld.so.cach,在命令和动态链接库之间建立对应关系;dev下基本终端设备和linuxrc中用到的设备:
console、ram、null、systty、tty1、tty2和hda1;mnt为hda1的挂载点。


              最后创建压缩的initrd ramdisk映像。


              运行df 看看/dev/ram0的字节数,在我的计算机上1684K
;


              转换当前目录至/root并卸载/dev/ram0 umount /dev/ram0


              拷贝/dev/ram0成映像文件 dd if=/dev/ram0 of=initrd.img bs=1k count=1684


              产生压缩的映像文件initrd.img.gz,运行gzip -9v initrd.img


              3.3启动



              系统的启动需要依靠flash盘
,通过LILO把系统启动信息写入flash盘主引导区。


将flash盘作为第一主盘hda,而将装有普通Linux的硬盘作为第一从盘hdb并从它启动
。在flash硬盘上创建ext2文件系统,将它挂载至
/mnt/flash目录。在flash盘上建立boot目录,将压缩的文件系统和initrd映像拷贝至boot目录下,同时将Linux内核、引导区
记录boot.b、引导区映射map拷贝至其下。普通Linux系统中建立LILO配置文件ramlilo.conf,配置文件如下:


              boot=/dev/hda



              map=/mnt/flash/boot/map



              install=/mnt/flash/boot/boot.b



              prompt



              timeout=50
               image=/mnt/flash/boot/vmlinuz



                append= “ramdisk_size=30000”



                label=embedded



                root=/dev/ram



                initrd=/mnt/flash/boot/initrd.img.gz



                运行命令lilo –C ramlilo.conf ,将启动信息写入flash的主引导区MBR。


                重新启动计算机,登陆后运行mount,我们看到如下两项:


                /dev/ram on / ext2 (rw)


                none on /proc type proc (rw)


                这显示只有ramdisk被挂载,制作成功。


                4 结论


在我们制作的嵌入式Linux中进行各种操作,速度非常快,而且系统很稳定。没有出现因为根文件系统损坏而导致系统进入手工维护界面的现象。用它作为
HTTP网络服务器、网络监视器、宽带通信设备管理器或者其他需要长时间不停运行的机器,都有很高的应用价值。
             



dd if=/dev/zero of=/dev/ram bs=1k count=2048

mke2fs -vm0 /dev/ram 2048

在ramdisk上建立2M的ext2文件系统;

mkdir /mnt/ram

mount /dev/ram /mnt/ram

cp -a /mnt/1/1/* /mnt/ram/

umount /dev/ram  

dd if=/dev/ram bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz



*******************************

Filesystem            
1K-块       
已用     可用 已用% 挂载点


/dev/hda2            
26571532   5003036  20196948  20% /


/dev/hda1              
124427     45584    
72419  39% /boot


/dev/shm               
257312        
0    257312   0% /dev/shm


/dev/hda3            
10154020    176964   9452936   2%
/home


/dev/hdc1             
6198404   1558524   4325008  27% /mnt/lfs


/dev/ram1                 2011      1671       340  84% /mnt/ram