本帖最后由 xcoder 于 2016-3-19 21:02 编辑
实战4 创建根文件系统
根文件系统(rootfs)是linux中一个很重要的文件系统,它在Linux启动时被挂载,文件系统中保存了一些系统工具和配置文件,在Linux启动时扮演重要的角色。在许多嵌入式系统中,常常使用使用BusyBox制作根文件系统。BusyBox是一个开源的工具,它将许多小工具、命令集成到一个单一的程序中。这一章我们就来学习如何使用BusyBox制作一个简单的根文件系统。 1. 新建根文件系统目录rootfs,根文件系统的所有内容都从这个目录展开。 #mkdir -p /home/ubuntu/pcduino/rootfs
|
2.创建根文件系统基本目录。 #sudo mkdir dev proc sys mnt tmp lib
#ls
dev lib lost+found mnt proc sys tmp
|
3.使用git命令下载BusyBox源码。 # cd /home/ubuntu/pcduino
# git clone git://git.busybox.net/busybox
# cd busybox
# ls
applets Config.in docs include LICENSE Makefile.flags print utils selinux TODO_unicode … |
4.配置BusyBox,可根据需要选择BusyBox内置的工具,也可暂时不做改动直接保存退出。
图4.1 BusyBox配置界面
5.修改Makefile,指定交叉编译器。
164修改行改为: CROSS_COMPILE?= arm-linux-gnueabihf-
190修改行改为: ARCH ?= arm
6.编译BusyBox。
7.安装目标文件到rootfs目录。 #sudo make CONFIG_PREFIX= /home/ubuntu/pcduino/rootfs install
|
8.拷贝动态链接库到根文件系统。 #cd /home/ubuntu/pcduino/rootfs
#sudo cp –rf
/home/ubuntu/pcduino/gcc-linaro-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/* ./lib/
|
9.拷贝基本配置到根文件系统。 #sudo cp -rf /home/ubuntu/pcduino/busybox/examples/bootfloppy/etc home/ubuntu/pcduino/rootfs/
|
10. 创建设备文件。
# cd /home/ubuntu/pcduino/rootfs
# sudo mknod dev/console c 5 1
# sudo mknod dev/null c 1 3
|
11. 修改fstab文件。
fstab是描述系统中存储设备和文件系统信息的文本文件,它会被fsck、mount、umount的等命令使用。每个文件系统独立一行描述,每行六个字段,分别是: - fs_spec存储设备,如硬盘:/dev/sda1,NFS:<host>:<dir>,或者一些虚拟的文件系统如procfs - fs_file文件系统的挂载目录 - fs_vfstype文件系统类型,如ext2、proc、sysfs等 - fs_mntops挂载选项,包括读写属性、是否自动挂载等 - fs_freq dump命令使用 - fs_passnofsck命令使用 字段间使用空格或TAB分隔,行首使用#可注释当前行。更详细信息可在虚拟机上执行命令man fstab查看。我们的根文件系统比较简单,fstab文件内容如下: #cd /home/ubuntu/pcduino/rootfs/etc
#sudo vi fstab
/dev/root / ext2 rw,noauto 0 1
proc /procproc defaults 0 0
tmpfs /tmptmpfs mode=1777 0 0
sysfs /sys sysfs defaults 0 0
|
12.创建inittab文件并添加如下内容。 # sudo vi inittab
::sysinit:/etc/init.d/rcS
::askfirst:~/bin/sh
|
BusyBox init程序会解析/etc/inittab文件,根据inittab文件的描述创建各种子进程。inittab文件中每行一条规则,格式如下: <id> : <runlevels> :<action> : <process> id :表示这个子进程要使用的控制台,如果省略,则使用与init进程一样的控制台。 runlevels:嵌入式系统通常不用,可以省略。 action:表示init进程如何控制这个子进程,具体取值见下表。 表4.1 init action定义 名称
| 执行条件
| 说明
| sysinit | 系统启动后最先执行 | 指定初始化脚本路径,只执行一次,init进程等待它结束才继续执行其它动作 | wait
| 系统执行完sysinit进程后
| 只执行一次,init进程等待它结束才继续执行其它动作
| once | 系统执行完wait进程后 | 只执行一次,init进程不等待它结束 | respawn | 启动完once进程后 | init进程监测发现子进程退出时,重新启动它,永不结束.如Shell命令解释器 | askfirst | 启动完respawn进程后 | 与respawn类似,不过init进程先输出“PleasepressEntertoactivatethisconsole”,等用户输入回车后才启动子进程。 | shutdown | 系统关机时 | 即重启、关闭系统时执行的程序 | restart | 系统重启时 | init进程重启时执行的程序,通常是init程序本身先重新读取、解析/etc/inittab文件,再执行restart程序 | ctrl+alt+del | 按下Ctrl+Alt+Del键时 | 按Ctrl+Alt+Del组合键时执行的程序 |
process:要执行的程序,它可以是可执行的二进制程序,也可以是脚本。 当前根文件系统目录结构如下: # cd /home/ubuntu/pcduino/rootfs
# ls -al
total 27
drwxr-xr-x 2 root root 3072 4月 19 20:35 bin
drwxr-xr-x 2 root root 1024 4月 19 20:37 dev
drwxr-xr-x 3 root root 1024 4月 19 20:41 etc
drwxr-xr-x 3 root root 1024 4月 19 20:37 lib
lrwxrwxrwx 1 root root 11 4月 19 20:35 linuxrc -> bin/busybox
drwx------ 2 root root 12288 4月 19 20:32 lost+found
drwxr-xr-x 2 root root 1024 4月 19 20:36 mnt
drwxr-xr-x 2 root root 1024 4月 19 20:36 proc
drwxr-xr-x 2 root root 3072 4月 19 20:35 sbin
drwxr-xr-x 2 root root 1024 4月 19 20:36 sys
drwxr-xr-x 2 root root 1024 4月 19 20:36 tmp
drwxr-xr-x 4 root root 1024 4月 19 20:35 usr
drwxr-xr-x 2 root root 1024 4月 19 20:36 var
|
至此,我们完成了根文件系统中所有目录、文件的创建。 13.文件系统的使用。 我们采用SD卡保存根文件系统共内核使用,通常有两种方式, 方式一,将上述建立的目录、文件打包成一个单独的根文件系统镜像文件,再将其写入SD卡指定分区位置,该分区就可以被挂载和使用。 方式二,首先将SD卡指定分区格式化为某一类型的文件系统,然后将根文件系统的中的所有目录、文件拷贝到这个分区中。
先来看方式一,目标是生成单独一个根文件系统镜像文件,制作方法如下: 13.1创建空白镜像文件。使用dd命令,生成的rootfs.img文件的内容全部是0,大小为32M。 # cd /home/ubuntu/pcduino
#sudo dd if=/dev/zero of=rootfs.img bs=32M count=1
1+0 records in
1+0 records out
33554432 bytes (34 MB) copied, 0.0791148 s, 424 MB/s
|
13.2将镜像文件格式化。 #sudo mkfs.ext2 rootfs.img
mke2fs 1.42.9 (4-Feb-2014)
rootfs.img is not a block special device.
Proceed anyway? (y,n) y
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
8192 inodes, 32768 blocks
1638 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=33554432
4 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193, 24577
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
|
格式化之后,rootfs.img文件数据不再全部是0,此时已经包含了一个ext2格式的文件系统,但还没有任何内容。为了能够将前面创建的根文件系统所需的目录、文件拷贝到rootfs.img中,首先需要将其挂载到某个目录,这样才能使用cp等这样的命令进行目录、文件的拷贝。
13.3挂载镜像文件到虚拟机。linux中存在一种特殊块设备,对应的块设备文件: # ls -l /dev/loop*
brw-rw---- 1 root disk 7, 0 8月 16 12:36 /dev/loop0
brw-rw---- 1 root disk 7, 1 8月 16 12:36 /dev/loop1
brw-rw---- 1 root disk 7, 2 8月 16 12:36 /dev/loop2
brw-rw---- 1 root disk 7, 3 8月 16 12:36 /dev/loop3
brw-rw---- 1 root disk 7, 4 8月 16 12:36 /dev/loop4
brw-rw---- 1 root disk 7, 5 8月 16 12:36 /dev/loop5
brw-rw---- 1 root disk 7, 6 8月 16 12:36 /dev/loop6
brw-rw---- 1 root disk 7, 7 8月 16 12:36 /dev/loop7
|
这些loop设备可以将普通的镜像文件映射成虚拟的块设备,使得访问镜像文件就像访问一个块设备一样。mount命令支持以loop方式挂载一个文件系统镜像文件,如我们将rootfs.img挂载到/mnt目录: # sudo mount ./rootfs.img /mnt -o loop=/dev/loop0
|
挂载之后,所有/mnt目录的改动,都会导致文件rootfs.img内容的改变。
13.4拷贝根文件系统内容到/mnt目录。 #cp –rf /home/ubuntu/pcduino/rootfs/* /mnt/
|
13.5从/mnt目录卸载文件系统镜像。
此时,rootfs.img文件中包含了所有根文件系统内容,使用dd命令将rootfs.img文件写入SD卡启动分区,下一章我们将详细介绍刷写方法。
对于方式二,十分容易理解,首相将SD卡挂载到虚拟机上,类似前文格式化rootfs.img文件一样格式化SD卡启动分区 # sudo mkfs.ext2 /dev/mmcblk0p2
|
在将根文件系统目录、文件拷贝到新格式化的分区目录中即可。 # cp –rf /home/ubuntu/pcduino/rootfs/* /mnt/<sd>/
|
这里就不再展开讲解了。
本章主要介绍了使用BusyBox制作根文件系统的过程,顺带解释了根文件系统的有代表性的文件作用。我们将在下一章进一步说明如何更新根文件系统到SD卡,以及前几章中编译镜像的使用。
|