在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。
1 最小根文件系统
我们先推理一下最小的根文件系统都需要哪些程序或模块。Linux内核启动init进程,需要加载init程序,所以,init程序是必需的。init进程在运行过程中会读取用户配置文件,所以/etc/inittab也是需要的(当然使用默认的也是可以的)。在/etc/inittab中如果配置了一些应用程序或者脚本,那么这些应用程序和脚本也是根文件系统所必需的。还有一个比较重要的模块就是c语言库,因为只要使用了库函数的应用程序都需要依赖c语言库。上述分析的这些都是围绕计算机系统的处理器来考虑的,从I/O设备角度来考虑,根文件系统还有一个不可缺少的模块就是控制台/dev/console。
现将最小根文件系统依赖的模块总结如下:
- init程序。
- /etc/inittab。
- 在/etc/inittab中注册的应用程序。
- c语言动态库。
- /dev/console;/dev/NULL(/etc/inittab格式中省略id时使用)。
2 使用busybox编译init应用程序
Linux系统中的应用程序千千万,但是在编译环节都默默遵守着同一个操作流程:配置->编译->安装。所以本小节不光是介绍如果构建根文件系统,还顺便介绍一下如何交叉编译一个应用程序。
2.1 配置
首先,从官网拿到busybox1.7.0的源码,解压缩。然后进行配置。
大部分保持默认配置即可。只需要关注两个配置:交叉编译工具链和Tab自动补全。
2.1.1 配置交叉编译工具链
busybox1.7.0源码使用make menuconfig不支持配置交叉编译工具链,所以我们选择直接修改Makefile。
修改如下:
# busybox1.7.0源码根目录下的Makefile文件
# 修改前
176 CROSS_COMPILE ?=
# 修改后
176 CROSS_COMPILE ?= arm-linux-
CROSS_COMPILE是交叉编译工具链的前缀,如果是空白则会使用当前平台的编译工具(非交叉编译)。
2.1.2 Tab自动补全
配置指令在按Tab键后自动补全功能需要使用make menuconfig,使用搜索功能可以快速定位。配置后的结果如下图所示。
2.2 编译
首先需要搞清楚编译最终生成的是什么。通过查看Makefile中的第一个目标我们知道,最终生成的其实就是一个应用程序 busybox 。我们只需要简单地 make 一下就可以生成该目标了。
# busybox1.7.0源码根目录下的Makefile文件
487 # The all: target is the default when no target is given on the
488 # command line.
489 # This allow a user to issue only 'make' to build a kernel including modules
490 # Defaults busybox but it is usually overridden in the arch makefile
491 all: busybox # 编译最终生成的目标
2.3 安装
什么是安装?安装都做了哪些事情?为什么需要安装?
安装这个概念其实也很好理解。比如你买了一台空调,需要安装师傅上门安装。首先,他要把空调搬到你们家(这就好比是cp或mv操作);然后需要给你配遥控器(这就好比是ln或export操作)。
安装简单总结就是 搬移+链接 。为什么需要安装也就很好解释了:空调需要安到你家而不是大街上;而且要搞个遥控器方便你使用。
busybox安装时需要按照INSTALL文件中的说明进行,对于交叉编译 千万不能 直接make install。
应该按照下述步骤进行:
- 创建一个自定义安装的文件夹,例如: mkdir -p /work/nfsroot/minifs。
- 然后使用带参数的install指令进行安装,例如:make CONFIG_PREFIX=/work/nfsroot/minifs install。
# busybox1.7.0源码根目录下的INSTALL文件
1 Building:
2 =========
3
4 The BusyBox build process is similar to the Linux kernel build:
5
6 make menuconfig # This creates a file called ".config"
7 make # This creates the "busybox" executable
8 make install # or make CONFIG_PREFIX=/path/from/root install
安装完成后的结果如下:
# 在ubuntu系统终端中
albert@ubuntu:/work/busybox-1.7.0 $ cd /work/nfsroot/minifs
/work/nfsroot/minifs
albert@ubuntu:/work/nfsroot/minifs $ ll
total 20
drwxrwxr-x 8 albert albert 4096 Oct 28 00:43 ./
drwxrwxr-x 3 albert albert 4096 Oct 28 00:46 ../
drwxrwxr-x 2 albert albert 4096 Oct 28 00:41 bin/
lrwxrwxrwx 1 albert albert 11 Oct 28 00:41 linuxrc -> bin/busybox*
drwxrwxr-x 2 albert albert 4096 Oct 28 00:41 sbin/
drwxrwxr-x 4 albert albert 4096 Oct 28 00:41 usr/
我们发现安装过程已经自动建立了bin/、usr/等目录,如果进入这些目录,会发现其中的指令都是busybox的软链接。
至此,busybox(包含了init程序)编译安装完成。
3 创建/etc/inittab
接下来需要创建/etc/inittab文件。
# 在ubuntu系统终端中
albert@ubuntu:/work/nfsroot/minifs $ mkdir etc
albert@ubuntu:/work/nfsroot/minifs $ ls
bin etc linuxrc sbin usr
albert@ubuntu:/work/nfsroot/minifs $ cd etc
albert@ubuntu:/work/nfsroot/minifs/etc $ vi inittab
albert@ubuntu:/work/nfsroot/minifs/etc $ ls
inittab
albert@ubuntu:/work/nfsroot/minifs/etc $
inittab中仅仅添加一行配置:
# /etc/inittab文件
::askfirst:-/bin/shell
4 创建/dev/console和/dev/null
接下来需要使用 mknod 指令创建两个虚拟的设备文件。为什么要搞虚拟文件呢?为了统一,这是Linux的设计哲学——操作硬件设备就像操作文件一样简单。为了防止劝退,有关虚拟文件系统方面的详细知识依然往后放。
创建的过程如下:
# 在ubuntu系统终端中操作
# 首先查看一下ubuntu系统下的这两个文件。
albert@ubuntu:/work/nfsroot/minifs $ ls -al /dev/console /dev/null
crw------- 1 root root 5, 1 Oct 18 07:43 /dev/console #其中c代表是字符设备,5是主设备号,1是从设备号。
crw-rw-rw- 1 root root 1, 3 Sep 28 20:22 /dev/null
albert@ubuntu:/work/nfsroot/minifs $ mkdir dev
albert@ubuntu:/work/nfsroot/minifs $ ls
bin dev etc linuxrc sbin usr
albert@ubuntu:/work/nfsroot/minifs $ cd dev
albert@ubuntu:/work/nfsroot/minifs/dev $ mknod console c 5 1
mknod: ‘console’: Operation not permitted
albert@ubuntu:/work/nfsroot/minifs/dev $ sudo mknod console c 5 1
[sudo] password for albert:
albert@ubuntu:/work/nfsroot/minifs/dev $ sudo mknod null c 1 3
albert@ubuntu:/work/nfsroot/minifs/dev $ ls -al
total 8
drwxrwxr-x 2 albert albert 4096 Oct 29 00:40 .
drwxrwxr-x 7 albert albert 4096 Oct 29 00:39 ..
crw-r--r-- 1 root root 5, 1 Oct 29 00:40 console
crw-r--r-- 1 root root 1, 3 Oct 29 00:40 null
5 安装glibc
安装glic动态库的过程其实也很简单,就是将交叉编译工具链中的glibc库中的so文件全部拷贝到/work/nfsroot/minifs/lib目录下即可。
操作如下:
# 在ubuntu系统终端中操作
albert@ubuntu:/work/nfsroot/minifs $ mkdir lib
albert@ubuntu:/work/nfsroot/minifs $ ls
bin dev etc lib linuxrc sbin usr
albert@ubuntu:/work/nfsroot/minifs $ echo $PATH #查看我自己的交叉编译工具链的安装位置(可选)。
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/share/tools/gcc-3.4.5-glibc-2.3.6/bin
albert@ubuntu:/work/nfsroot/minifs $ cd lib
# 拷贝时一定要记得加-d选项,不然库文件会有重叠,这样会非常浪费空间。
albert@ubuntu:/work/nfsroot/minifs/lib $ cp -ad /usr/share/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/*.so* . #这里的源路径(存放交叉编译工具链和C库的路径)请根据自己的情况进行修改。
albert@ubuntu:/work/nfsroot/minifs/lib $ ls
ld-2.3.6.so libcrypt.so.1 libm.so libnss_files-2.3.6.so libnss_nis.so.2 librt.so.1
ld-linux.so.2 libc.so libm.so.6 libnss_files.so libpcprofile.so libSegFault.so
libanl-2.3.6.so libc.so.6 libnsl-2.3.6.so libnss_files.so.2 libpthread-0.10.so libstdc++.so
libanl.so libc.so_orig libnsl.so libnss_hesiod-2.3.6.so libpthread.so libstdc++.so.6
libanl.so.1 libdl-2.3.6.so libnsl.so.1 libnss_hesiod.so libpthread.so.0 libstdc++.so.6.0.3
libBrokenLocale-2.3.6.so libdl.so libnss_compat-2.3.6.so libnss_hesiod.so.2 libpthread.so_orig libthread_db-1.0.so
libBrokenLocale.so libdl.so.2 libnss_compat.so libnss_nis-2.3.6.so libresolv-2.3.6.so libthread_db.so
libBrokenLocale.so.1 libgcc_s.so libnss_compat.so.2 libnss_nisplus-2.3.6.so libresolv.so libthread_db.so.1
libc-2.3.6.so libgcc_s.so.1 libnss_dns-2.3.6.so libnss_nisplus.so libresolv.so.2 libutil-2.3.6.so
libcrypt-2.3.6.so libm-2.3.6.so libnss_dns.so libnss_nisplus.so.2 librt-2.3.6.so libutil.so
libcrypt.so libmemusage.so libnss_dns.so.2 libnss_nis.so librt.so libutil.so.1
6 制作yaffs2文件系统镜像
制作yaffs2文件系统镜像需要使用 mkyaffs2 工具,该工具其实就是一个应用程序。
获取该工具有三种方式:
- 下载源码,自己make制作。
- 直接下载mkyaffs2工具。
- 私信我,我直接发你~
拿到该工具后,将该工具放到ubuntu的/usr/local/bin目录下。然后做如下操作:
# 在ubuntu系统终端中操作
albert@ubuntu:/work/nfsroot $ ls
minifs
albert@ubuntu:/work/nfsroot $ mkyaffs2image
mkyaffs2image: image building tool for YAFFS2 built Oct 28 2020
usage: mkyaffs2image dir image_file [convert]
dir the directory tree to be converted
image_file the output file to hold the image
'convert' produce a big-endian image from a little-endian machine
albert@ubuntu:/work/nfsroot $ mkyaffs2image minifs/ minifs.yaffs2
... #省略制作过程的大量打印
albert@ubuntu:/work/nfsroot $ ls #我们看到minifs.yaffs2就是我们最终想要的根文件镜像
minifs minifs.yaffs2
至此,我们想要的最小根文件镜像已经得到,将其通过J-link或者uboot下载到Nand Flash中即可使用。
如下图,系统可以顺利启动。
恭喜你又坚持看完了一篇博客,又进步了一点点!如果感觉还不错就点个赞再走吧,你的点赞和关注将是我持续输出的哒哒哒动力~~