如何在Linux中创建一个简单的文件系统,并配置到启动项

782 阅读4分钟

需要完成的任务:

  1. 利用initrd.img机制,建立一个简单文件系统(v0.5版本),使得内核用该文件系统启动后可以直接获得一个shell
  2. 在grub启动配置文件当中增加一个入口用于测试新建的initrd.img
  3. 整个文件系统在启动后运行在内存中,不需要调用硬盘资源。

实验记录

创建一个简单的文件系统

首先,需要创建一个基础的文件系统结构,这通常包括必要的目录和文件。对于一个非常基础的系统,至少需要以下目录:

  • /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

image.png

发现系统说找不到这个文件,这是怎么回事呢?实际上shell 程序依赖于一些动态库,我们需要找出这些依赖并复制到文件系统中。

复制必要的库文件

由于sh需要的链接库bash都有,我们只需要找到bash的库文件就好。

使用ldd查看bash需要的链接库

ldd /usr/bin/bash

image.png

这里面我们发现这些链接库都指向了一个具体的文件位置,但是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

image.png

再次尝试运行sheel程序

sudo chroot myfilesystem /bin/bash

image.png

这次我们成功了!让我们试试ls指令。

image.png

ls指令并没有被移到这个系统里面,我们想看文件怎么办呢?我们可以使用tab的自动补全功能去查看。

image.png

上面这些就是我们目前可以使用的命令了。至此,我们已经成功获得了一个最简单的文件系统,我们想要退出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

image.png

接下来重启,开机时按住shift进入grub界面,并选择我们自己的系统。

image.png

我们成功进入了我们的系统,可以通过Tab查看我们的文件内容

image.png

如果我们需要加命令,可以把对应命令加入到bin文件里面。