4. 我实现并开源的tmpfs+initramfs方案
读者读到这里应该已经能想到我的方案【1】了吧,那就是在initramfs中,不生成块设备zram,而是生成一个tmpfs作为最终的根目录。是不是听起来很简单?其实实现起来更简单。我的源里核心代码有三个文件,init, ramdisk.sh, gen_initramfs-ARCH.sh。
4.1. init
init文件,是initramfs.img的入口,修改或编写这个文件是本方案的核心。我的init文件修改自/usr/share/genkernel/defaults/linuxrc,是gentopo的内核编译软件genkernel提供的gentoo默认脚本。如果你用的是archlinux,应该看/usr/lib/initcpio/init。源里init文件最后几行代码是我写的,做的事情是用tmpfs生成一个占用一半系统内存的/ram_chroot,从/mnt/.ramdisk文件夹同步根目录数据。如果你的内存很大能轻松容纳整个磁盘,也可以直接从磁盘根目录同步过来。我的/mnt/.ramdisk文件夹是在ramdisk.sh中生成的,生成的时候把系统中一些没什么用的文件夹去掉了。最后一句switch_root之后,系统就boot到内存系统中了。注意下面脚本在启动之前先umount了实际硬盘,这也是从原理到性能都优于GentooPlayer方案的地方。
- mkdir /ram_chroot
- mount -t tmpfs -o rw,noatime none /ram_chroot
- cp -a "${CHROOT}"/mnt/.ramdisk/* /ram_chroot/
- mount --move /proc /ram_chroot/proc
- mount --move /sys /ram_chroot/sys
- mount --move /dev /ram_chroot/dev
- umount ${CHROOT}
- good_msg "Switching to real root: switch_root /ram_chroot ${init} ${init_opts}"
- exec switch_root /ram_chroot "${init}"
复制代码
4.2. ramdisk.sh
ramdisk.sh其实是可有可无的,生成一个小一些新的root_fs放在/mnt/.ramdisk/,exclude掉了一些没用又占空间的文件,比如/usr/src内核源码等等。主要是因为我的树莓派只有2g内存,虽然也足够把整个系统都同步过来,不过为了战未来还是写了这段脚本。需要指出的是,我的系统中/bin /lib /lib64 /sbin四个目录是软链接的,并没同步过去,如果你的系统原本不是软链接就全同步过去。总之让/mnt/.ramdisk看起来和/基本上一样就好了,注意不要把/mnt自己也同步过去了。
4.3. gen_initramfs-ARCH.sh
树莓派和x86我是分开写的,主要是因为树莓派用config.txt控制启动入口,x86我用了grub控制启动入口。我同时提供了如下树莓派的config.txt,意思是kernel/initramfs的文件名分别是kernel和initramfs,你如果不喜欢我的口味可以按需改脚本,注意别改followkernel这个是关键字。
- kernel kernel
- initramfs initramfs followkernel
复制代码
gen_initramfs-ARCH.sh文件一共要做三件事:先mount了/boot分区,该删除删除该备份备份,之后从服务器把交叉编译生成的内核文件同步到/boot,如果你是本地编译就不需要这步了;之后把刚刚出炉的initramfs解压缩,把init文件替换为我们刚刚改好的那个,再重新打包回initramfs.img;最后把这个文件部署到/boot分区,配置grub等等启动项。以x86/grub为例,现在boot到新生成的这个initramfs.img就是内存启动,boot到编译生成的那个就是硬盘启动。需要指出两点,一个是这段脚本中我利用了genkernel的一个配置生成了一个名为kernel的内核链接,和一个名为initramfs的initramfs.img链接;一个是我在编译内核时用的xz压缩。如果你不喜欢这种设置可能需要对应修改自己的代码。
4.4. 关于是否成功执行
启动系统之后执行df,如果你的根目录类型是none或者tmpfs就对了。更进一步还可以执行mount命令不用参数,可以看到目前mount的所有目录中没有磁盘。注意曾经mount过的磁盘是不能再次mount的,这个方案也允许用户自己执行mount /dev/sda2 /mnt; mount /dev/sda1 /mnt/boot 这种命令。
4.5. 关于日常维护
逻辑上,直接boot到刚刚生成的磁盘分区就可以日常维护了,不过实际上有更简单的办法。直接boot到内存系统中,用mount命令把磁盘挂载起来,之后用我在本站的帖子【6】中介绍的chroot方法,就可以直接进入硬盘系统使用包管理软件进行软件安装了,记得最后执行ramdisk.sh同步一下即可。
【1】https://github.com/zhjie/ramroot
【6】http://erji.net/forum.php?mod=vi ... =2284715&extra=
|