一起分析Linux系统设计思想——04构建根文件系统(一)

在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。

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,使用搜索功能可以快速定位。配置后的结果如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tsXU2moP-1603906327969)(04%E6%9E%84%E5%BB%BA%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%EF%BC%88%E4%B8%80%EF%BC%89.assets/image-20201028234511283.png)]

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。

应该按照下述步骤进行:

  1. 创建一个自定义安装的文件夹,例如: mkdir -p /work/nfsroot/minifs。
  2. 然后使用带参数的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中即可使用。

如下图,系统可以顺利启动。
在这里插入图片描述


恭喜你又坚持看完了一篇博客,又进步了一点点!如果感觉还不错就点个赞再走吧,你的点赞和关注将是我持续输出的哒哒哒动力~~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿越临界点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值