需要完成的任务:
- 利用initrd.img机制,建立一个简单文件系统(v0.5版本),使得内核用该文件系统启动后可以直接获得一个shell
- 在grub启动配置文件当中增加一个入口用于测试新建的initrd.img
- 整个文件系统在启动后运行在内存中,不需要调用硬盘资源。
实验记录
创建一个简单的文件系统
首先,需要创建一个基础的文件系统结构,这通常包括必要的目录和文件。对于一个非常基础的系统,至少需要以下目录:
- /bin - 存放基本命令和程序
- /dev - 设备文件
- /etc - 配置文件
- /proc - 系统信息
- /sys - 系统信息
- /tmp - 临时文件
- /root - root用户的家目录
- /sbin - 系统管理命令
我们创建一个这个目录并进入。
mkdir -p myfilesystem/bin myfilesystem/lib myfilesystem/lib64 myfilesystem/etc myfilesystem/dev myfilesystem/proc myfilesystem/sys myfilesystem/tmp
cd myfilesystem
复制 shell 程序
由于我在做实验的时候发现bash貌似无法在初始化时启动,所以启动系统时我使用sh,然后在sh中启动bash
使用 cp 命令将 shell 程序复制到自己文件系统的 /bin 目录下:
cp /bin/sh ./bin
cp /bin/bash ./bin
尝试运行这个bash
使用chroot去尝试运行这个环境
cd ~
sudo chroot myfilesystem /bin/bash
发现系统说找不到这个文件,这是怎么回事呢?实际上shell 程序依赖于一些动态库,我们需要找出这些依赖并复制到文件系统中。
复制必要的库文件
由于sh需要的链接库bash都有,我们只需要找到bash的库文件就好。
使用ldd查看bash需要的链接库
ldd /usr/bin/bash
这里面我们发现这些链接库都指向了一个具体的文件位置,但是linux-vdso.so.1没有,这是为什么呢?实际上它是一个虚拟的动态共享对象,它由内核提供,不占用磁盘空间。因此,我们不需要(也不可能)将linux-vdso.so.1复制到我们的chroot环境中。
接下来,我们将这些库文件移动到我们的环境下面。
mkdir myfilesystem/lib/x86_64-linux-gnu
cp /lib/x86_64-linux-gnu/libtinfo.so.6 ./myfilesystem/lib/x86_64-linux-gnu/
cp /lib/x86_64-linux-gnu/libc.so.6 ./myfilesystem/lib/x86_64-linux-gnu/
cp /lib64/ld-linux-x86-64.so.2 ./myfilesystem/lib64
再次尝试运行sheel程序
sudo chroot myfilesystem /bin/bash
这次我们成功了!让我们试试ls指令。
ls指令并没有被移到这个系统里面,我们想看文件怎么办呢?我们可以使用tab的自动补全功能去查看。
上面这些就是我们目前可以使用的命令了。至此,我们已经成功获得了一个最简单的文件系统,我们想要退出chroot环境,可以使用exit命令。
将该环境打包成initrd映像文件
接下来,我要把我们的系统打包好给内核调用。
首先,我们在根目录需要一个init脚本,这个脚本是内核启动initrd最初运行的脚本,我们要在里面进行挂载,运行sheel等关键操作。我们现在只需要让它使用/bin/sh进行初始化,然后启动/bin/bash
vim myfilesystem/init
#!/bin/sh
exec /bin/bash
然后我们需要修改该文件的权限使其可执行。
chmod +x myfilesystem/init
接着,我们就可以把这个文件系统打包成一个initrd映像文件。这个文件将在启动时被加载到内存中,作为根文件系统使用,这个部分使用root进行。
su
cd myfilesystem
find . | cpio -o -H newc | gzip > /boot/my-initrd.img
更新grub配置
接下来,我们需要编辑 GRUB 的配置文件来添加一个新的启动项。这通常通过编辑 /etc/grub.d/40_custom 文件来实现:
sudo vim /etc/grub.d/40_custom
在这个文件的末尾添加一个新的菜单项:
menuentry 'My Custom Environment' {
linux /boot/vmlinuz rw
initrd /boot/my-initrd.img
}
- linux /boot/vmlinuz rw 指定了要使用的内核。这里 /boot/vmlinuz 是内核文件的路径,需要根据实际情况替换,由于我们只是在内存中运行,不需要用到硬盘,所以不需要root=xxx去指定根环境。
- initrd /boot/my-initrd.img 指定了 initrd 文件的路径。
更新GRUB并重启
更新grub
update-grub
接下来重启,开机时按住shift进入grub界面,并选择我们自己的系统。
我们成功进入了我们的系统,可以通过Tab查看我们的文件内容
如果我们需要加命令,可以把对应命令加入到bin文件里面。