Linux 最小根文件系统
启动流程
Linux系统启动顺序如下:
graph LR A[Bootloader] --> |启动|B[Linux内核] -->|识别| C[根文件系统] --> |运行|D[应用]
参考之前的rCore项目,首先会执行由QEMU提供的BootLoader,然后启动rCore,最后再运行操作系统,相当于根文件系统。
Linux 文件系统结构
理论上是这样的
graph TD root["/"] root --> bin["/bin"] root --> sbin["/sbin"] root --> dev["/dev"] root --> etc["/etc"] root --> lib["/lib"] root --> home["/home"] root --> root_dir["/root"] root --> usr["/usr"] root --> var["/var"] root --> proc["/proc"] root --> mnt["/mnt"] root --> tmp["/tmp"]
其中:
- /bin 存放所有用户可用的、最基本的命令(理论上)
- /sbin 存放管理员可用的命令
- /dev
存放设备文件,一切外设都可以在Linux中以文件的形式访问,例如
/mnt/nvme0n1p1
就代表一个 nvme 固态的分区 - /etc 各种配置文件
- /lib 放共享库和可加载模块
- /home 用户目录,每个普通用户都会在该目录下有个家目录
- /root 根用户的家目录
- /usr
并不是 user,而是 Unix System Resource。里面有
/usr/bin
,/usr/sbin
,/usr/lib
等子文件夹,之所以这么做,是因为在资源受限的设备中,根文件系统与 /usr 分区不在一个物理分区,开机后先挂载根文件系统,再运行/bin
中的mount
指令挂载 /usr 分区。 因此 /usr 中的程序和库都是相对上层,非必须的。不过在普通的发行版中,/bin是一个符号链接,指向了/usr/bin,因为在现代硬件上,存储空间已经够大辣。 - /var
顾名思义,存放可变数据,例如
/var/log
存放日志,/var/tmp
存放持久临时文件。 - /proc 是一个虚拟文件系统,将内核的状态、硬件信息等以文件形式暴露出来。用于用户空间与内核空间交互,主要用于查询和配置系统运行时的状态。
- /mnt 临时文件系统挂载点,例如U盘,移动硬盘等,插入后会出现在/dev目录下,然后需要挂载到此处访问。
- /tmp 顾名思义,存放临时文件,重启后会被清空。
以Ubuntu24.04为例,实际是这样的:
lrwxrwxrwx 1 root root 7 Apr 22 2024 bin -> usr/bin/
drwxr-xr-x 2 root root 4.0K Feb 26 2024 bin.usr-is-merged/
drwxr-xr-x 2 root root 4.0K Apr 22 2024 boot/
drwxr-xr-x 15 root root 3.8K Jun 20 10:52 dev/
drwxr-xr-x 108 root root 4.0K Jun 20 10:52 etc/
drwxr-xr-x 3 root root 4.0K Jun 19 00:29 home/
-rwxrwxrwx 1 root root 2.6M Apr 24 07:34 init*
lrwxrwxrwx 1 root root 7 Apr 22 2024 lib -> usr/lib/
drwxr-xr-x 2 root root 4.0K Apr 8 2024 lib.usr-is-merged/
lrwxrwxrwx 1 root root 9 Apr 22 2024 lib64 -> usr/lib64/
drwx------ 2 root root 16K Jun 19 00:28 lost+found/
drwxr-xr-x 2 root root 4.0K Jan 7 04:13 media/
drwxr-xr-x 6 root root 4.0K Jun 19 00:28 mnt/
drwxr-xr-x 2 root root 4.0K Jan 7 04:13 opt/
dr-xr-xr-x 299 root root 0 Jun 20 10:52 proc/
drwx------ 6 root root 4.0K Jun 19 11:25 root/
drwxr-xr-x 21 root root 600 Jun 20 10:52 run/
lrwxrwxrwx 1 root root 8 Apr 22 2024 sbin -> usr/sbin/
drwxr-xr-x 2 root root 4.0K Mar 31 2024 sbin.usr-is-merged/
drwxr-xr-x 2 root root 4.0K Jun 19 00:28 snap/
drwxr-xr-x 2 root root 4.0K Jan 7 04:13 srv/
dr-xr-xr-x 13 root root 0 Jun 20 10:52 sys/
drwxrwxrwt 10 root root 4.0K Jun 20 10:53 tmp/
drwxr-xr-x 12 root root 4.0K Jan 7 04:13 usr/
drwxr-xr-x 13 root root 4.0K Jun 19 00:28 var/
System-V 启动顺序
-
加载 /boot/zImage 内核与 .dtb 后缀的设备树
-
/sbin/init 内核启动它作为第一个进程 作用
- 读配置文件
- 根据配置文件启动其他APP
在基于rCore的系统中,第一个进程是终端,目的也是为了启动其他APP。因此,对于最简系统,后面的步骤可以不需要,到这里就算是启动系统了。
-
读配置文件 /etc/inittab
-
启动其他APP
- 启动时需要读取/lib下的动态链接库
制作busybox最小根文件系统
编译
-
首先修改Makefile中的
CROSS_COMPILE
变量指定交叉编译工具链,当然也可以在执行make的时候指定,或者修改环境变量,不过还是直接改Makefile默认值方便:CROSS_COMPILE ?= arm-buildroot-linux-gnuebihf-
-
执行
make menuconfig
进入TUI设置界面,这里默认就行 -
执行
make -j$(nproc)
编译 到这里才发现我没装工具链,参考开发手册下载后, 在~/.config/fish/config.fish
中添加set -x ARCH arm set -x CROSS_COMPILE arm-buildroot-linux-gnueabihf- fish_add_path /home/szy/Softwares/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/
-
在当前目录下安装
make CONFIG_PREFIX=tmp install
然后tmp目录结构如下:
.
├── bin
├── linuxrc -> bin/busybox
├── sbin
└── usr
准备内核和DTS
cd tmp
mkdir boot
cp ~