嵌入式linux根文件系统制作--busybox

2019-07-12 15:07发布

class="markdown_views prism-tomorrow-night"> busybox是构造文件系统最常用的软件工具包,它被非常形象地称为嵌入式Linux系统中的“瑞士军刀”,因为它将许多常用的Linux命令和工具结合到了一个单独的可执行程序(busybox)中。
虽然与相应的GNU工具比较起来,busybox所提供的功能和参数略少,但在比较小的系统(例如启动盘)或者嵌入式系统中已经足够了。
busybox在设计上就充分考虑了硬件资源受限的特殊工作环境。它采用一种很巧妙的办法减少自己的体积:所有的命令都通过“插件”的方式集中到一个可执行文件中,在实际应用过程中通过不同的符号链接来确定到底要执行哪个操作。采用单一执行文件的方式最大限度地共享了程序代码,甚至连文件头、内存中的程序控制块等其他系统资源都共享了,对于资源比较紧张的系统来说,真是最合适不过了。在busybox的编译过程中,可以非常方便地加减它的“插件”,最后的符号链接也可以由编译系统自动生成。

目的:

理清楚 根文件系统的制作流程。所以,这里不纠结细节。

系统环境及工具:

操作系统:Ubuntu12.04
交叉编译工具:arm-linux-gcc4.4.3
busybox源码包:busybox-1.25.0.tar.bz2

根文件系统制作–busybox配置编译安装:

动态链接的busybox只有几百K,即使静态链接的也只有1MB左右。
在创建一个最小的根文件系统时,使用busybox的话,只需要在/dev目录下创建必要的设备节点、在/etc目录下创建一些配置文件就可以了;如果busybox使用动态链接的话,还需要在/lib目录下包含库文件。
这里选择动态链接。

解压源码包:

#tar -jxvf busybox-1.25.0.tar.bz2

修改Makefile配置

进入busybox-1.25.0目录,修改Makefile文件如下: ARCH ?= arm CROSS_COMPILE ?= /usr/local/arm/4.4.3/bin/arm-linux- (与你自己主机的arm-linux-gcc安装目录一样)

配置BusyBox

#make menuconfig Busybox Settings —>
Build Options —>
[*]Build shared libbusybox
[ ] Produce a binary for each applet, linked against libbusybox
[ ] Produce additional busybox binary linked against libbusybox Busybox Settings —>
Installation Options (“make install” behavior) —>
(/nfsdir/tools/rootfs) BusyBox installation prefix // 编译生成文件的存放路径
注意:如果你是在虚拟机上安装busybox,安装不可直接执行make INSTALL,必须在虚拟机下自己创建一个文件夹,将安装路径指向这个文件夹的路径。再执行 make CONFIG_PREFIX=/path/from/root install 否则会破坏系统。
其他都保持默认
关于需要注意的一些选项说明如下:
Busybox Settings —>
Build Options —>
[ ] Build BusyBox as a static binary (no shared libs) (NEW)
这个意思是运行busybox才动态链接库,busybox需要的库要我们提供 Busybox Settings —>
Installation Options (“make install” behavior) —>
What kind of applet links to install (as soft-links) —>
设置busybox生成后各种命令均为指向busybox主程序的软链接 Busybox Settings —>
Busybox Library Tuning —>
(255) History size
[*] History saving (NEW) // 支持历史记录
[*] Tab completion (NEW) // 支持Tab补全操作 选项Applets就是将busybox支持的几百个命令分门别类,我们可以在各个门类下选择想要的命令。

编译安装

#make #make install

构建根文件系统

至此busubox的安装就完成了,现在查看/nfsdir/tools/rootfs文件夹,会发现多了下面几个文件:
bin linuxrc sbin usr
可以在bin目录查看,busybox只有970K

创建其他所需文件夹(根据FHS标准)

mkdir dev etc home lib media mnt opt proc sys tmp var root

添加相应的库

需要添加的库是从编译busybox所使用的交叉编译工具里拷贝的,但交叉编译工具里的库文件很多,不必全部拷贝。
那么我们怎么知道哪些库是需要的呢?
可以用一下方法确定 [root@localhost bin]# arm-linux-readelf -d busybox Dynamic section at offset 0xf16b4 contains 25 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libm.so.6] 0x00000001 (NEEDED) Shared library: [libc.so.6] 而ld-linux.so.3属于固有需要的库,所以busybox至少需要三个库:ld-linux.so.3、libm.so.6、libc.so.6 下面要睁大眼睛了,上面的库都是链接文件,不要把链接文件拷进去了,真正的文件没拷贝
[root@localhost lib]# ls -l libc.so.6
lrwxrwxrwx 1 root root 11 Apr 23 21:13 libc.so.6 -> libc-2.8.so [root@localhost lib]# ls -l libm.so.6
lrwxrwxrwx 1 root root 11 Apr 23 21:13 libm.so.6 -> libm-2.8.so [root@localhost lib]# ls -l ld-linux.so.3
lrwxrwxrwx 1 root root 9 Apr 23 21:13 ld-linux.so.3 -> ld-2.8.so 所以要把ld-linux.so.3、libm.so.6、libc.so.6和libc-2.8.so、libm-2.8.so、ld-2.8.so都拷贝到/lib下。
但是上面的这几个库只是busybox运行所需要的库,这个时候系统虽然可以启动,但会出现下面的打印信息: feed_wdg: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directory 这个意思是由于缺少libgcc_s.so.1库,导致看门狗程序启动不了,然后看到开发板过以后重启了,所以要想正常运行还需要拷贝libgcc_s.so和libgcc_s.so.1 但是实际使用的时候要一个一个去查看嘛,这样太麻烦了,所以一般把正常需要的库都拷贝到/lib下,这样也不会太大,包括:
ld-linux:动态链接库,必需
libc: 标准c函数库,必需
libm: 数学库,一般需要
libdl: 用于动态装载共享库,较少用到
libcrypt: 加密附加库,需要认证的程序用到,较少用
libpthread: POSIX线程库,一般需要

添加配置文件(即/etc下的文件)

1、添加inittab文件:
仿照busybox的example/inittab文件,创建/linuxrc的初始化配置文件/etc/inittab
该文件中指定linuxrc初始化完成后运行/etc/init.d.rcS脚本。然后在console运行一个shell,该shell不需要登陆。 # /etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::once:/usr/sbin/telnetd -l /bin/login ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r 2、添加init.d/rcS文件 #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH # # Trap CTRL-C &c only in this shell so we can interrupt subprocesses. # mount -a # 挂载在/etc/fstab中定义的所有挂载点 mkdir -p /dev/pts #为telnetd创建pts目录 mount -t devpts devpts /dev/pts #挂载pts目录 echo /sbin/mdev > /proc/sys/kernel/hotplug # 设置热插拔事件处理程序为mdev mdev -s #设备节点维护程序mdev初始化 mkdir -p /var/lock hwclock -s feed_wdg & ifconfig lo 127.0.0.1 ifconfig eth0 192.168.2.99 /bin/hostname -F /etc/HOSTNAME 3、添加HOSTNAME文件,
内容就是代表主机名,可以随意定,如:
Blue
4、添加fstab文件: #device mount-point type options dump fsck order proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0 tmpfs /dev tmpfs defaults 0 0 var /dev tmpfs defaults 0 0 ramfs /dev ramfs defaults 0 0 5、添加profile文件
根据inittab文件的内容console::askfirst:-/bin/sh,
在启动脚本etc/init.d/rcS执行完后将在终端启动一个shell。Shell启动过程中会根据文件/etc/profile配置登陆环境。
所以需要添加profile文件,内容如下: USER="`id -un`" LOGNAME=$USER PS1='[u@h W]# ' # 这个显示的是命令行下的主机名和用户名格式,如:[root@Blue etc]# PATH=$PATH HOSTNAME=`/bin/hostname` export USER LOGNAME PS1 PATH 6、添加group和passwd文件:
group内容如下: root:x:0:root passwd内容如下: root::0:0:root:/:/bin/sh 到此/etc配置完毕,包含如下:
HOSTNAME fstab group init.d inittab passwd profile

在/dev/下创建设备节点:

mknod console c 5 1 mknod null c 1 3 至此,/nfsdir/tools/rootfs目录下就是一个非常小的根文件系统,开发板可以将它作为网络根文件系统直接启动。如果要烧入开发板,还需要将它制作为一个文件,称为映像文件。
所谓制作文件系统映像文件,就是将一个目录下的所有内容,按照一定的格式存放到一个文件中,这个文件可以直接烧写到存储设备上去。当系统启动后,挂接这个设备,就可以看到与原来目录一致的内容。
制作不同类型的文件系统映像文件,需要使用不同的工具。

制作yaffs2文件系统映像文件

进入到/nfsdir/tools/(根文件系统的上次目录) [root@localhost tools]# mkyaffs2image rootfs root.bin /* mkyaffs2image工具是交叉编译工具自带的*/ 生成的root.bin镜像可直接拷贝到nand flash的文件系统分区,接下来就可以直接启动了

制作jffs2文件系统映像文件

mkfs.jffs2 -n -s 512 -e 16KiB -d rootfs -o root.jffs2 命令中,“-n”表示不要在每个擦除块上都加上清除标志,“-s 512”指明一页大小为512字节,“-e 16KiB”指明一个擦除块大小为16KB,“-d”表示根文件系统目录,“-o”表示输出文件。 上面只是制作了一个最简单的文件系统,实际可以根据自己的需要添加启动程序、丰富自己的配置及功能等

编译错误解决参考

1、make出现如下错误: miscutils/nandwrite.c: In function 'nandwrite_main': miscutils/nandwrite.c:151: error: 'MTD_FILE_MODE_RAW' undeclared (first use in this?function) miscutils/nandwrite.c:151: error: (Each undeclared identifier is reported only once miscutils/nandwrite.c:151: error: for each function it appears in.) scripts/Makefile.build:197: recipe for target 'miscutils/nandwrite.o' failed make[1]: *** [miscutils/nandwrite.o] Error 1 Makefile:742: recipe for target 'miscutils' failed make: *** [miscutils] Error 2 解决办法: MTD_FILE_MODE_RAW在/usr/include/mtd/mtd-abi.h中定义。将/usr/include/mtd/mtd-abi.h拷贝到busybox的include文件中。 #gedit miscutils/nandwrite.c 修改头文件如下: #include "libbb.h" #include "mtd-abi.h" #include 编译可以通过。 2、继续make,出现如下错误: util-linux/blkdiscard.c: In function 'blkdiscard_main': util-linux/blkdiscard.c:72: error: 'BLKSECDISCARD' undeclared (first use in this function) util-linux/blkdiscard.c:72: error: (Each undeclared identifier is reported only once util-linux/blkdiscard.c:72: error: for each function it appears in.) scripts/Makefile.build:197: recipe for target 'util-linux/blkdiscard.o' failed make[1]: *** [util-linux/blkdiscard.o] Error 1 Makefile:742: recipe for target 'util-linux' failed make: *** [util-linux] Error 2 解决办法:
BLKSECDISCARD在/usr/include/linux/fs.h中定义,方法如上所述,将/usr/include/linux/fs.h拷贝到busybox的include文件中linux下。 #gedit util-linux/blkdiscard.c 修改内容如下: #include 编译通过。 到这里rootfs基本上已经制作出来,有些内容需要的,可根据自己rootfs的需要进行自己增加。最后将rootfs目录制作成镜像后,就可以烧写到开发板上了。

后记:

inittab文件格式:

:::: 在什么时间启动什么进程 当id 和runlevels为空时,就会出现::双冒号的形式
id: 进程所使用的终端名
runlevels:不用填写
action: 是程序执行的时机,包括:sysinit, respawn, askfirst, wait, once, restart, ctrlaltdel, and shutdown.等
process:将要执行的应用程序或脚本;
sysinit: 系统初始化的时候,放在最前面
respawn,askfirst是一样的,如果process意外终止啦,系统会讲其重启
askfirst 会有提示Please press Enter to activate this console
wait: 该进程一定要执行完,才能执行下一个
once, 进程如果意外终止,那么不会重启