1、文件系统简介?
为什么需要文件系统?
如果没有文件系统,我们访问磁盘的时候,必须按照扇区号来访问,且要记住哪个文件存在哪个扇区号,文档见越来越多的时候,人是不可能记住这些的。有了文件系统这套软件后,他会对硬盘的扇区进行管理,将按照扇区号访问变成按照目录和文件名的方式访问。我们在按照目录和文件名去访问一个文件时,文件系统会将这个目录+文件名转换成对应的扇区号去访问。
不同格式的文件系统有什么区别?
不同格式的文件系统的差异就在于他们对这些扇区的管理策略和方法不同,譬如坏块管理、碎片管理等。但是他们提供的功能是一样的。就像小轿车都是载人的,但是他们实现方式可能不一样,有一些用柴油,有一些用电动的。文件系统的格式由他们的制作工具决定。
文件系统的两种存在形式。
文件夹形式的文件系统就是在开发主机上,如Ubuntu上,用mkdir去创建一系列文件夹,再向这些文件夹拷贝必要的内容。然后在开发板上用nfs的方式去挂载刚刚在Ubuntu上制作的文件系统,这种方式适合调试,因为只要开发板和Ubuntu断开链接,内核就启动失败了。当文件系统调试完成后,我们就需要把文件夹形式的文件系统用文件系统制作工具做成镜像文件形式的文件系统。制作成镜像后只要把这个镜像烧录到硬盘中就可以使用。
2、文件系统的启动过程。
第一步:
在uboot结束时会向内核传递参数,其中一个就是bootargs,这个参数中就有文件体统的信息。参数如下bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3。root=/dev/mmcblk0p2表示根文件系统烧录在第一个块设备,第三个分区中。init=/linuxrc 表示内核启动成功后,去运行的第一个用户态的进程init就是根文件系统/目录下的linuxrc。为什么是这样以,因为用=画上等号啦,哈哈。就是这样。
第二步:
内核启动成功后会去挂载根文件系统,然后执行文件系统中的init进程,init进程会轮询解析inittable配置文件,去执行相应程序,具体如何接续后面讲。
3、busybox制作
什么是busybox?
busybox是一个可执行程序,我们内核启动后的第一个用户进程init,即linuxrc,就是busybox程序中的某一个子函数,还有ls pwd等也都是busybox的子函数。这就是bosybox能化成万千程序的原理。
busybox制作步骤:
a.下载busybox源代码 ,进入buzybox官网https://busybox.net,点击Download Source->选择busybox-1.24.1.tar.bz2下载.
b.把下载来的压缩包解压到一个目录如/root/rootfs/busybox/目录下,这个目录是自己创建。
c.然后开始编译,编译过程和l编译inux内核很像,因为busybox本来就是参考内核写的代码。先make menuconfig,进入配置图形界面,具体如何配置这里不细讲了。配置好后直接make就好了。make可能为出错,错误找百度解决。
d.编译成功后输入make install安装busybox。默认的安装目录是当前目录下root/rootfs/busybox/_install/中,但我们要更改这个默认路径为/root/rootfs/rootfs,默认路径是在make menuconfig中配置修改。因为在制作文件系统时我们需要调试,调试一般用nfs挂载文件形式的文件系统,我们要把busybox安装到自己制作的根文件系统中,即/root/rootfs/rootfs,在Ubuntu中这个目录会被配置成nfs server的挂载目录。
e.安装完成后,在安装的路径下 ls可以看到bin sbin usr目录和一个linuxrc可执行程序。linuxrc是指向bin/busybox的符号链接,所以说执行linuxrc的实质是执行busybox,也就是linux内核启动挂载文件系统后,在应用层执行的第一个进程init进程就是busybox。但是bosybox不仅仅只是linuxrc,我们操作ls pwd 等常用指令程序实质也都是在执行busybos。可以换一种方式理解,linuxrc ls pwd 都是 busybox进程的其中一个子函数,buzybox是一个主函数main,当你输入ls时,由于ls是指向buzybox的符号链接,所以实质是执行busybox的main函数,且main函数的传入参数argv[0] = ls,然后根据这个传入参数,去执行相应的子函数ls_main函数。当你输入pwd时,相当于传入参数argv[0] = pwd,然后根据这个传入参数会去执行pwd_main函数。最后温馨提示:ls等执行程序在安装路径的bin目录下。
f.上面的步骤做完后,我们在开发板上用nfs挂载方式启动看看会有什么效果。当然是要去挂载文件形式的文件系统,bootargs也要修改一下。setenv bootargs root=/dev/nfs nfsroot=192.168.1.42:/root/rootfs/rootfs ip=192.168.1.25:192.168.1.42:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200。
4、inittable配置文件。
接着上一步往下走,在开发板上去启动Linux内核,发现文件系统挂载成功了,内核也正常启动了,但是会一直打印错误信息。这个问题的解决办法就是,在/etc/目录下添加inittable配置文件。inittable具体内容如下
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:-/sbin/reboot
#umount all filesystem
::shutdown:/bin/umount -a -r
#restart init process
::restart:/sbin/init
内核启动挂载文件系统后会执行linuxrc,linuxrc是指向buzybox的符号链接,所以实质是执行了buzybox,这个时候buzybox main函数的输入传参argv[0]=linuxrc,根据传入参数最终会去调用子函数init_mian(init进程的源代码)。init_mian会一直轮询去解析inittable配置文件,这个解析是从开机开始一直到关机为止的。inittable是按照一定的格式去解析的。每个解析项之间用":"隔开,一个共4个解析项,就算解析项为空,冒号也不能省略。如配置文件中的第一行的第3个解析项sysinit,表示在开机的时候会去执行第四个解析项/etc/init.d/rcS,rcS是个脚本文件,详细内容后边讲。配置文件的第5行的第3个解析项shutdown,表示关机的时候会去执行第4个解析项/bin/umount -a -r,buzybox会根据-a这个选项,取消挂载挂载所以文件。还有一个解析项respawn,上边文件没有但是也很重要,他的作用是只要第四个解析项停止运行了,就会去重拉,有点向守护进程。
rcS是一个脚本文件,这个目录和文件名字都是不能改的,具体内容如下
!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
//umask是设置默认权限的,在touch mkdir创建文件或者目录是的默认权限
umask 022
export PATH runlevel prevlevel
//挂载文件,包括proc sys等虚拟文件
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
/bin/hostname -F /etc/sysconfig/HOSTNAME
ifconfig eth0 192.168.1.10
//a.sh是自己写的shell脚本,在a.sh可以去执行自己编译的一些程序,如hello程序
//如果hello程序是依赖动态库的,那么还有在文件系统中添加lib.so文件
source /usr/bin/a.sh
5、镜像文件系统制作
根文件系统调试制作完成后,要把文件形式的变成镜像形式的,烧录到开发版中。
在/root/rootfs/目录下新建一个tmp目录
mkdir ./tmp
在/root/rootfs/目录下,用专用工具制作镜像文件系统rootfs.ext2,工具Ubuntu自带的
dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
losetup /dev/loop1 rootfs.ext2
mke2fs -m 0 /dev/loop1 10240
镜像做好后挂载到tmp目录下,这样就可以通过tmp目录往镜像中添加东西了
mount -t ext2 /dev/loop1 ./tmp/
进入tmp目录把制作的文件系统添加到tmp中
cp /root/rootfs/rootfs/* /root/rootfs/tmp -rf
卸载掉,文件系统就做好了
umount /dev/loop1
losetup -d /dev/loop1
之后只要把rootfs.ext2烧录到开发板就好。