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

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

1 为什么要完善

好多概念的建立,技术的创新最终都是为了解决某个或某类问题。所以,问题 往往是众多行为的根源。

那么我们为什么要完善上一篇建立的最小根文件系统呢?

因为ps、reboot、df、top等指令都不好用,会报下述错误。

# arm9嵌入式设备上执行下述指令
/ # ps
  PID  Uid        VSZ Stat Command
ps: can't open '/proc': No such file or directory
/ # reboot
reboot: can't open '/proc': No such file or directory

2 什么是挂载

挂载(mount)这个概念还蛮抽象的,即使你mount指令用的再溜,如果不仔细考虑这个概念,也只能浮在表面。mount是一个动作,就好比是牵线搭桥,和媒婆儿干的是一件事。那桥的两端是谁呢?一端是根文件系统,另外一端是其他文件系统。

到这里必须要解释根文件系统是个什么东西了(在前面的文章中我们跳过了这个概念)。根文件系统并不固定是某种类型的文件系统,表明的只是它的用途——作为 文件的根 。说到根就涉及到 ,文件系统中的文件就是按照树形拓扑进行组织的。系统启动过程一定要先挂载一个文件系统作为根文件系统,后期再挂载的文件系统都是 枝叶文件系统 ,先长根再长枝叶很正常对不对?

那么什么样的文件系统才可以或者说有资格作为根文件系统最先被挂载呢?如果该文件系统中有init程序、/etc/inittab、在/etc/inittab中注册的应用程序(比如-/bin/sh)、c语言动态库、/dev/console & /dev/null这些必要模块(详细见上篇的分析)的话,该文件系统就可以作为根文件系统被内核优先挂载。比如yaffs、yaffs2、jffs2、nfs类型的文件系统只要包含了上述列出的程序都可以作为根文件系统。

再回到挂载,举一个大家很好理解的例子。比如你有好多小家电需要通电,但是家里墙上只有一个插座,所以你找来了几个插排(好比文件系统),而且插排的品牌都不太一样。接下来你要做什么呢?挑一个大功率的插排(好比根文件系统)首先插到墙上的插孔(插的这个动作就是mount)。接下来再将其他的插排插到这个大功率的插排上(好比挂载其他文件系统)。最后,你就可以方便地使用你的小家用电器了(你可以方便地访问文件啦~)。

是不是对mount又有了新的认识?最后,记住:mount就是 映射


3 完善proc目录

3.1 直接mount的方式

我们发现ps和reboot指令都是因为缺少/proc目录导致的。/proc目录存在的意义就是挂接proc类型的文件系统。proc是一种虚拟文件系统,存储的是内核运行状态的一系列特殊文件,这些虚拟的文件其实是内核生成并存储在RAM中的,设备掉电就会消失。

接下来就使用mount指令直接mount一下proc文件系统。

在上一篇的基础上增加根文件系统内容。创建/proc目录,增加/etc/init.d/rcS文件并修改/etc/inittab文件。

  1. 创建/proc目录
# 在Ubuntu系统中操作
albert@ubuntu:/work/nfsroot/minifs $ ls
bin  dev  etc  lib  linuxrc  sbin  usr
albert@ubuntu:/work/nfsroot/minifs $ mkdir proc #创建proc目录
albert@ubuntu:/work/nfsroot/minifs $ ls
bin  dev  etc  lib  linuxrc  proc  sbin  usr
  1. 编辑/etc/inittab文件
# 在Ubuntu系统中操作
# 在inittab中添加Linux内核启动配置脚本文件(/etc/init.d/rcS文件)
::sysinit:/etc/init.d/rcS

Tips:/etc/init.d/rcS文件是内核启动脚本文件,有任何想要在系统启动阶段想要操作的shell指令都可以添加到该文件中。至于rcS的全拼我个人理解是runtime configuration Script,如有勘误请留言指教,谢谢~

  1. 创建/etc/init.d/rcS文件并编辑
# 在Ubuntu系统中操作
# 创建(根文件系统安装目录)/etc/init.d/rcS文件
albert@ubuntu:/work/nfsroot/minifs/etc $ mkdir init.d
albert@ubuntu:/work/nfsroot/minifs/etc $ ls
init.d  inittab
albert@ubuntu:/work/nfsroot/minifs/etc $ cd init.d
albert@ubuntu:/work/nfsroot/minifs/etc/init.d $ touch rcS
albert@ubuntu:/work/nfsroot/minifs/etc/init.d $ ls -al
total 12
drwxrwxr-x 2 albert albert 4096 Oct 31 16:21 .
drwxrwxr-x 3 albert albert 4096 Oct 31 16:17 ..
-rw-rw-r-- 1 albert albert   25 Oct 31 16:21 rcS
albert@ubuntu:/work/nfsroot/minifs/etc/init.d $ chmod +x rcS #一定要注意添加可执行权限
albert@ubuntu:/work/nfsroot/minifs/etc/init.d $ ls -al
total 12
drwxrwxr-x 2 albert albert 4096 Oct 31 16:21 .
drwxrwxr-x 3 albert albert 4096 Oct 31 16:17 ..
-rwxrwxr-x 1 albert albert   25 Oct 31 16:21 rcS
albert@ubuntu:/work/nfsroot/minifs/etc/init.d $ 
  # 在Ubuntu系统中操作
  # 编辑(根文件系统安装目录)/etc/init.d/rcS文件内容
  # mount -t type dev dir
  mount -t proc none /proc #将proc文件系统映射到/proc目录

Tips:注意要根据上下文区分开Ubuntu中的路径和嵌入式设备上的路径,不要搞混了,这里说的创建/etc/init.d/rcS文件是嵌入式设备上的路径。不要破坏了Ubuntu本身的系统。

3.2 使用fstab的方式

3.2和3.1是并列关系,这两者方法都可以完成proc文件系统的挂载,选择一种即可,推荐使用fstab的方式。因为在rcS文件中mount指令如果使用的多了会显得很乱,重复代码过多,这时候就需要用到 表驱动/数据驱动 思想来解决这个问题了。fstab就是这种思想的产物。fstab用来管理所有file system的挂载参数,而rcS文件中只需要mount -a就够了。

接下来,演示一下这个优化过程。

  1. 编辑/etc/init.d/rcS文件内容
  # 在Ubuntu系统中操作
  # 编辑(根文件系统安装目录)/etc/init.d/rcS文件内容
  # mount -t type dev dir
  #mount -t proc none /proc #将proc文件系统映射到/proc目录
  mount -a	#将上一行代码修改为本行
  1. 创建/etc/fstab文件
# 在Ubuntu系统中操作
# 创建(根文件系统安装目录)/etc/fstab文件
albert@ubuntu:/work/nfsroot/minifs $ cd etc/
albert@ubuntu:/work/nfsroot/minifs/etc $ touch fstab
albert@ubuntu:/work/nfsroot/minifs/etc $ ls
fstab  init.d  inittab
  1. 编辑/etc/fstab文件内容
  # 在Ubuntu系统中操作
  # 编辑(根文件系统安装目录)/etc/fstab文件
  # device    mount-point    fs-type    options  dump  fsck  order    
    none      /proc          proc       defaults 0     0     

下面对表头做一个说明:

条目 含义 说明
device 要挂载的设备 因为Linux中所有对象皆文件,所有每个硬件设备都会映射成一种虚拟文件。比如块设备该字段可能是/dev/mtdblock3;nfs的该字段格式是<host>:<dir>;但是对于和设备不相关的文件系统,比如proc,该字段可以随意填,一般填写为文件系统类型或者none。
mount-point 挂载点 就是path路径。
fs-type 文件系统类型 文件系统类型大概有下述几种:yaffs、yaffs2、jffs2、ext2、ext3、nfs、proc、tmpfs、sysfs等等。

4 完善dev目录

为什么要完善dev目录呢?一个原因是设备很多,手工创建比较繁琐;另外一个原因是为了支持热插拔。

我们接下来完善dev目录使用的是 mdev (udev的简化版本)机制。mdev是一个程序,运行时会扫描/sys/class和/sys/block中所有的类设备目录,如果在目录中含有名为 dev 的文件,且文件中包含了设备号,则mdev就通过这些信息为这个设备在/dev下自动创建设备节点。

使用mdev的步骤如下:

  1. 挂载sysfs文件系统到/sys目录下。不做这步操作是无法运行mdev指令的。
  2. 挂载tmpfs文件系统到/dev目录下。
  3. 创建/dev/pts目录并挂载devpts文件系统到/dev/pts目录下。注意创建/dev/pts目录一定要在第2步之后。
  4. 将mdev程序调用加到/proc/sys/kernel/hotplug文件中:echo /sbin/mdev > /proc/sys/kernel/hotplug。做这一步是为了保证热插拔时自动运行mdev指令,以便自动创建和删除设备节点文件。
  5. 设备启动时先扫描一次:mdev -s。保证在设备启动时创建当前扫描到的所有设备节点文件。

Tips:

1.tmpfs是一种虚拟内存的文件系统,它既可以使用 RAM,也可以使用交换分区。将/dev挂载tmpfs的好处就是可以让设备节点文件脱离flash保存,提升运行速度。

2.pts是远程虚拟终端。devpts即远程虚拟终端文件设备。通过/dev/pts可以了解目前远程虚拟终端的基本情况。通过对相应的设备文件进行操作,就可以达到操作硬件的目的。而所谓的虚拟内核文件设备,是直接和内核打交道的。内核是在内存中的,所以说才叫虚拟,因为这个设备文件并不代表真正的硬件,只是存在于内存中的虚拟设备。通过访问这样的文件,可以达到和内核即使通信的目的(读/写)。


我们实际操作一次。

  1. 创建/sys目录
# 在Ubuntu系统中操作
albert@ubuntu:/work/nfsroot/minifs $ mkdir sys
  1. 编辑/etc/fstab文件
  # 在Ubuntu系统中操作
  # 编辑(根文件系统安装目录)/etc/fstab文件
  # device    mount-point    fs-type    options  dump  fsck  order    
    none      /proc          proc       defaults 0     0
    none      /sys           sysfs      defaults 0     0
    none      /dev           tmpfs      defaults 0     0
  1. 编辑/etc/init.d/rcS文件
  # 在Ubuntu系统中操作
  # 编辑(根文件系统安装目录)/etc/init.d/rcS文件
  mount -a
  mkdir /dev/pts
  mount -t devpts none /dev/pts
  echo /sbin/mdev > /proc/sys/kernel/hotplug
  mdev -s

5 制作yaffs2文件系统镜像并烧写

制作过程见上篇。烧写新的根文件系统镜像,运行起来的效果如下图:
在这里插入图片描述


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

猜你喜欢

转载自blog.csdn.net/weixin_44873133/article/details/109409831