(Ref: http://maozheng11.blog.hexun.com/22338272_d.html)
一、构建自己的交叉编译环境
二、u-boot移植
三、编译内核
四、构建文件系统
过程:
一、构建自己的交叉编译环境
嵌 入式设备由于不具备一定的处理器能力和存储空间,程序开发一般用PC来完成,然后将可执行文件下载到嵌入式系统中运行。这是目前嵌入式程序开发的不二选择 ——Host/target模式。但这引发了一个问题:由于Host和Target的处理器体系结构不同,我们不能直接用PC上既有的程序开发工具,必须 使用跨平台开发工具,即在Host上生成能在Target上运行格式的目标文件。以下我会简单的说一下怎么构建交叉编译环境,当然如果不想麻烦也可以到网 上去下载。
先下载binutils、gcc、glibc、linux-kernel等包和几个插件,可到 http://weintroub.com/~coldwell/toolchain/处下载,先解压glibc-2.3.5,打开INSTALL文件, 看其中对gcc、awk、sed等软件的要求,此处为:
GNU `make' 3.79 or newer
GCC 3.2 or newer
GNU `binutils' 2.13 or later
GNU `texinfo' 3.12f
GNU `awk' 3.0, or some other POSIX awk
Perl 5
GNU `sed' 3.02 or newer
GNU `autoconf' 2.53 or higher
GNU `gettext' 0.10.36 or later
1、设置环境变量
TARGET=arm-linux
PREFIX=/usr/arm
SYSROOT=${PREFIX}/sysroot
export ARCH=arm
export CROSS_COMPILE=${TARGET}-
export PATH=$PATH:${PREFIX}/bin
2、建立二进制工具
mkdir -p ${PREFIX}/src
cd ${PREFIX}/src
tar zxvf binutils-2.16.tar.gz
mkdir -p BUILD/binutils-2.16
cd BUILD/binutils-2.16
../../binutils-2.16/configure --prefix=${PREFIX} --target=${TARGET} --with-sysroot=${SYSROOT} && make && make install && echo ok (如果最后一行显示ok则表示安装成功)
3、建立内核头文件
cd ${PREFIX}/src
tar zxvf linux-2.6.10.tar.gz
ln -s linux-2.6.10 linux
zcat 2.6.10-at91.patch.gz | patch -d linux -p1
cd linux
make at91rm9200dk_defconfig
make include/linux/version.h
mkdir -p ${SYSROOT}/usr/include
cp -a ${PREFIX}/src/linux/include/linux ${SYSROOT}/usr/include/linux
cp -a ${PREFIX}/src/linux/include/asm-arm ${SYSROOT}/usr/include/asm
cp -a ${PREFIX}/src/linux/include/asm-generic ${SYSROOT}/usr/include/asm-generic
4、安装glibc头文件
cd ${PREFIX}/src
tar zxvf glibc-2.3.5.tar.gz
patch -d glibc-2.3.5 -p1 <ioperm.c.diff
cd glibc-2.3.5
tar xvfz ../glibc-linuxthreads-2.3.5.tar.gz
cd ..
mkdir -p BUILD/glibc-2.3.5-headers
cd BUILD/glibc-2.3.5-headers
../../glibc-2.3.5/configure --prefix=/usr --host=${TARGET} --enable-add-ons=linuxthreads --with-headers=${SYSROOT}/usr/include && make cross-compiling=yes install_root=${SYSROOT} install-headers && echo ok
touch ${SYSROOT}/usr/include/gnu/stubs.h
touch ${SYSROOT}/usr/include/bits/stdio_lim.h
5、建立初始编译器
cd ${PREFIX}/src
tar jxvf gcc-3.4.4.tar.bz2
patch -d gcc-3.4.4 -p1 < flow.c.diff
patch -d gcc-3.4.4 -p1 < t-linux.diff
mkdir -p BUILD/gcc-3.4.4-stage1
cd BUILD/gcc-3.4.4-stage1
../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c --with-sysroot=${SYSROOT} && make && make install && echo ok
6、建立c库
cd ${PREFIX}/src
mkdir -p BUILD/glibc-2.3.5
cd BUILD/glibc-2.3.5
BUILD_CC=gcc CC=${CROSS_COMPILE}gcc AR=${CROSS_COMPILE}ar RANLIB=${CROSS_COMPILE}ranlib AS=${CROSS_COMPILE}as LD=${CROSS_COMPILE}ld ../../glibc-2.3.5/configure --prefix=/usr --build=i386-redhat-linux --host=arm-linux --target=arm-linux --without-__thread --enable-add-ons=linuxthreads --with-headers=${SYSROOT}/usr/include && make && make install_root=${SYSROOT} install && echo ok
7、建立全套编译器
cd ${PREFIX}/src
mkdir -p BUILD/gcc-3.4.4
cd BUILD/gcc-3.4.4
../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --with-sysroot=${SYSROOT} && make && make install && echo ok
8、测试
1)编写一个HelloWorld程序,然后arm-linux-gcc helloworld.c -o helloworld
2)file helloworld
aa: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
如果显示出上面的输出,说明你编译了一个能在arm体系结构下运行的helloworld,证明你的编译工具做成功了。
二、u-boot移植
BootLoader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状 态,以便为最终调用操作系统内核准备好正确的环境。BootLoader是严重地依赖于硬件而实现的,特别是在嵌入式世界。
由于 BootLoader的实现依赖于CPU的体系结构,因此大多数BootLoader都分为stage1和stage2两大部分。依赖于CPU体系结构的 代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而stage2则通常用C语言来实现,这样 可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。
BootLoader的stage1通常包括以下步骤(以执行的先后顺序):
1、硬件设备初始化。
2、为加载BootLoader的stage2准备RAM空间。
3、 拷贝BootLoader的stage2到RAM空间中。(注:由于stage2通常是C语言执行代码,因此在考虑空间大小时,除了stage2可执行映 象的大小外,还必须把堆栈空间也考虑进来。一般情况下都是分出1M的RAM给它们,我的习惯是把RAM顶层的1M空间空出来分给它们,即 0x21f00000到0x21ffffff,当然也可以把RAM起始位置的1M空间分给他们)
4、设置好堆栈。
5、跳转到stage2的C入口点。
BootLoader的stage2通常包括以下步骤(以执行的先后顺序):
1、初始化本阶段要使用到的硬件设备。
2、检测系统内存映射(memory map)。
3、将kernel映像和根文件系统映像从flash上读到RAM空间中。
4、为内核设置启动参数。
5、调用内核。
如今能支持RAM cpu的BootLoader有好多个,其中支持类型最多,且最出名的是blob和u-boot,本篇就介绍一下我用u-boot往at91rm9200开发板上移植的过程:
1、cp -R at91rm9200dk myboard
1)cp at91rm9200dk.c myboard.c
2)vi Makefle
将COBJS := at91rm9200dk.o at45.o flash.o 改为 COBJS := myboard.o at45.o flash.o
3)添加Nor Flash驱动,芯片型号是MBM29LV320BE(FUJITSU)
vi flash.c
1>由于这个型号的Nor Flash有71个扇区,且前9个是8K,后62个是64K,因此加入
OrgDef OrgMBM29LV320BE[] =
{
{ 8, 8*1024 }, /* 8 * 8 kBytes sectors */
{ 63, 64*1024 }, /* 63 * 64 kBytes sectors */
};
2>加入
#define RESET 0xF0
3>
在函数void flash_identification (flash_info_t * info)中加入:
/* Read Reset */
MEM_FLASH_ADDR1 = FLASH_CODE1;
MEM_FLASH_ADDR2 = FLASH_CODE2;
MEM_FLASH_ADDR1 = RESET;
/* Go to Autoselect mode */
MEM_FLASH_ADDR1 = FLASH_CODE1;
MEM_FLASH_ADDR2 = FLASH_CODE2;
MEM_FLASH_ADDR1 = ID_IN_CODE;
/* Vendor type */
info->flash_id = FUJ_MANUFACT & FLASH_VENDMASK;
printf("FUJ and AMD\n");
/* AMD Flash */
info->flash_id |= AMD_ID_LV320B & FLASH_TYPEMASK;
printf("MBM29LV320B (32Mbit)\n");
4>
在函数ulong flash_init (void)中加入:
/* MBM29LV320BE Flash */
pOrgDef = OrgMBM29LV320BE;
flash_nb_blocks = sizeof (OrgMBM29LV320BE) / sizeof (OrgDef);
5>
在函数void flash_print_info (flash_info_t * info)中加入:
case (FUJ_MANUFACT & FLASH_VENDMASK):
printf("FUJ");
break;
case (AMD_ID_LV320B & FLASH_TYPEMASK):
printf("MBM29LV320BE (32Mbit\n)");
break;
6>
在函数int flash_erase (flash_info_t * info, int s_first, int s_last)中加入:
if ((info->flash_id & FLASH_VENDMASK) != (FUJ_MANUFACT & FLASH_VENDMASK))
{
return ERR_UNKNOWN_FLASH_VENDOR;
}
2、回到u-boot目录下,打开Makefile文件,加入(为了能make myboard_config):
myboard_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t myboard NULL at91rm9200
3、在u-boot目录下,打开MAKEALL文件,在
LIST_ARM9=" \
at91rm9200dk cmc_pu2 \
ap920t ap922_XA10 ap926ejs ap946es \
ap966 cp920t cp922_XA10 cp926ejs \
cp946es cp966 lpd7a400 mp2usb \
mx1ads mx1fs2 netstar omap1510inn \
omap1610h2 omap1610inn omap730p2 sbc2410x \
scb9328 smdk2400 smdk2410 trab \
VCMA9 versatile versatileab versatilepb \
voiceblue \
"
加入 myboard,即:
LIST_ARM9=" \
at91rm9200dk cmc_pu2 \
ap920t ap922_XA10 ap926ejs ap946es \
ap966 cp920t cp922_XA10 cp926ejs \
cp946es cp966 lpd7a400 mp2usb \
mx1ads mx1fs2 netstar omap1510inn \
omap1610h2 omap1610inn omap730p2 sbc2410x \
scb9328 smdk2400 smdk2410 trab \
VCMA9 versatile versatileab versatilepb \
voiceblue myboard \
"
4、cd include/configs,cp at91rm9200dk.h myboard.h,打开myboard.h文件
1)加入#define CONFIG_SKIP_LOWLEVEL_INIT (由于板子会自动进行初始化,所以此处要跳过去,否则会成为死循环)
2)由于我的板子上的Nor Flash是4M,所以把
#define PHYS_FLASH_SIZE 0x200000
改为
#define PHYS_FLASH_SIZE 0x400000
3)由于我的板子上的Nor Flash共71个扇区,所以把
#define CFG_MAX_FLASH_SECT 256
改为
#define CFG_MAX_FLASH_SECT 71
5、
export BUILD_DIR=/home/lb/abc
make distclean
make myboard_config
make all
在/home/lb/abc中会生成三个文件u-boot.bin、u-boot和u-boot.srec,我只需要u-boot.bin文件。
三、编译内核
Bootloader将内核加载到内存中,设定一些寄存器,然后将控制权交由内核,该过程中,关闭MMU功能。通常,内核都是以压缩的方式存放,如zImage,这里有两种解压方法:
1、使用内核自解压程序。
2、在Bootloader中增加解压功能。
使用该方法时内核不需要带有自解压功能,而使用Bootloader中的解压程序代替内核自解压程序。其工作过程与内核自解压过程相似:Bootloader把压缩方式的内核解压到内存中,然后跳转到内核入口处开始执行。
内核有多种启动方式,如下:
XIP(EXECUTE IN PLACE)是指直接从存放代码的位置上启动运行。
1、非压缩,非XIP
非XIP方式是指在运行之前需对代码进行重定位。该类型的内核以非压缩方式存放在Flash中,启动时由Bootloader加载到内存后运行。
2、非压缩,XIP
该 类型的内核以非压缩格式存放在ROM/Flash中,不需要加载到内存就能运行,Bootloader直接跳转到其存放地址执行。Data段复制和BSS 段清零的工作由内核自己完成。这种启动方式常用于内存空间有限的系统中,另外,程序在ROM/Flash中运行的速度相对较慢。
3、RAM自解压
压 缩格式的内核由开头一段自解压代码和压缩内核数据组成,由于以压缩格式存放,内核只能以非XIP方式运行。RAM自解压过程如下:压缩内核存放于 ROM/Flash中,Bootloader启动后加载到内存中的临时空间,然后跳转到压缩内核入口地址执行自解压代码,内核被解压到最终的目的地址然后 运行。压缩内核所占据的临时空间随后被Linux回收利用。这种方式的内核在嵌入式产品中较为常见。
4、ROM自解压
解压缩代码也能够以 XIP的方式在ROM/Flash中运行。ROM自解压过程如下:压缩内核存放在ROM/Flash中,不需要加载到内存就能运行,Bootloader 直接跳转到其存放地址执行其自解压代码,将压缩内核解压到最终的目的地址并运行。ROM自解压方式存放的内核解压缩速度慢,而且也不能节省内存空间。
先下载一个内核原文件和相对应的ARM内核补丁。通常情况下ARM内核不要超过1M,所以对自己没有用的选项都可以不选。
1、
cd linux-2.6.*
zcat ../2.6.*-at91.patch.gz |patch -p1
2、
vi Makefile
把
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
改为
ARCH ?= arm
CROSS_COMPILE ?= 相应交叉编译环境 (我的是arm-linux-)
3、
make at91rm9200dk_defconfig
make menuconfig
(注:配置ARMlinux的方法和配置官方Linux内核差不多,以下是我对内核的配置,可供大家参考:
[System Type] 平台支持
选择 ARM system type 为 Atmel AT91
选择 Atmel AT91 System-on-Chip==>Atmel AT91 Processor 为 AT91RM9200
其它选项都是用默认
[Gernel setup]通用配置
选择 Sysctl support
选择 System V IPC
这两个选项我也没有深入研究,不知不选是不是也可以?其它的都不要选了。
[Memory Technology Devices(MTD)] MTD 配置
选择 <*>Memory Technology Device(MTD) support 记着选择为“built-in”而不是“module”(前面的选项为“*”而不是“M”)
选择 <*>Mtd partitioning support MTD 分区支持
选择 <*>Caching block device access to MTD devices 支持 MTD作为BLOCK设备访问
进入【RAM/ROM/FLASH chip drivers- 】选项选择加载 FLASH 的驱动
选择 <*> Detect flash chips by Common Flash Interface (CFI) probe自动探测 CFI 接口的 FLASH 设备
选择 <*> Support for AMD/Fujistu flash chips 选择对 AMD/Fujistu FLASH 设备的支持
选择 <*> Support for ROM chips in bus mapping 支持 ROM 设备总线 MAP
其它选项不选,退回到上一级。
进入【Mapping drivers for chip access- 】选项
选择 <*> CFI Flash device mapped on ARM Integrator/P720T 支持 ARM 的 FLASH 分区
其它选项都不用选中。
[Networking Options] 网络选项
本选项全部为 built-in 方式。
选择<*> Packet socket
选择<*> Kernel/User netlink socket
选择<*> Unix domain sockets
选择<*> TCP/IP networking
选择<*> IP: multicasting 支持组播
选择<*> IP: kernel level autoconfiguration
选择<*> IP: DHCP support
选择<*> IP: BOOTP support
选择<*> IP: RARP support
其它的都可以不选。
[File systems] 文件系统
该目录下包含内核对各种文件系统的支持,可以根据需要选择想要的文件系统。
选择<*> Second extended fs support
选择<*> JFS filesystem support
进入[Miscellaneous filesystems]选项
选择<*> Jouralling Flash File System V2 (JFFS2) support内核支持 JFFS 和 JFFS2 文件系统
进入【Network File Systems- 】 网络文件系统子选项
选择<*> NFS file system support NFS 网络文件系统支持
选择<*> Provide NFSv3 client support 支持 NFS 版本 3 客户端
选择<*> Root file system on NFS 根文件系统采用 NFS
退回上级菜单,其它的都没有选中。
其它的配置可以根据目标系统的不同灵活配置,像IDE、Sound等和目标系统没关系的选项都可以去掉,因“板”而异吗。
)
make
4、
cp linux2.6.*/vmlinux /home/lb/kernel
cp linux2.6.*/arch/arm/boot/zImage /home/lb/kernel
5、
cd /home/lb/kernel
1)arm-linux-objcopy -O binary -S vmlinux linux.bin
2)gzip -v9 linux.bin
3)/home/lb/abc/tools/mkimage -A arm -O linux -T kernel -C gzip -a 0x20008000 -e 0x20008000 -d linux.bin.gz uImage
(
注:uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。
mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置,入口点在内存的那个位置以及映象名是什么。
参数说明:
-A 指定CPU的体系结构:
alpha Alpha
arm ARM
x86 Intel x86
ia64 IA64
mips MIPS
mips64 MIPS 64Bit
ppc PowerPC
s390 IBM S390
sh SuperH
sparc SPARC
sparc64 SPARC 64Bit
m68k MC68000
-O 指定操作系统类型,可以取以下值:
openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos
-T 指定映象类型,可以取以下值:
standalone、kernel、ramdisk、multi、firmware、script、filesystem
-C 指定映象压缩方式,可以取以下值:
none 不压缩
gzip 用gzip的压缩方式
bzip2 用bzip2的压缩方式
-a 指定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载
-e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头)
-n 指定映象名
-d 指定制作映象的源文件
)
得到了内核映射文件uImage
四、构建文件系统
在嵌入式Linux开发中, 往往需要为目标系统设置根文件系统, 这包括: 准备好根文件系统所需的内容, 选择目标系统的文件系统类型, 将根文件系统的内容转换为所用文件系统的格式, 将根文件系统安装到目标系统上。
常用的文件系统有:
1、ramdisk
ramdisk的优点: 读写速度非常快, 适合用来制作initrd。
ramdisk的缺点: 不具有永久性, 断电后无法保存. 且ramdisk大小不可更改, 浪费ram。
2、tmpfs
tmpfs是一个以虚拟内存为基础的文件系统,它的大小不是固定的, 这都是它区别于ramdisk的优点。
tmpfs以虚拟内存为基础, 所以它不同于ramdisk,ramdisk只能位于ram中, 而tmpfs可能位于交换分区中(Linux内核的虚拟内存资源同时来源于RAM和交换分区)。
tmpfs是个文件系统, 而不是块设备,同样和ramdisk比较: ramdisk是个块设备, 需要一个mkfs之类的命令将个做成某个格式的文件系统才能使用,而tmpfs是一个文件系统不是块设备,mount它即可使用。
3、cramfs
1)采用实时解压缩方式,但解压缩的时侯有延迟。
2)cramfs的数据都是经过处理、打包的,对其进行写操作有一定困难。所以cramfs不支持写操作,这个特性刚好适合嵌入式应用中使用Flash存储文件系统的场合。
3)在cramfs中,文件最大不能超过16MB。
4)支持组标识(gid),但是mkcramfs只将gid的低8位保存下来,因此只有这8位是有效的。
5)支持硬链接。但是cramfs并没有完全处理好,硬链接的文件属性中,链接数仍然为1.
6)cramfs的目录中,没有“.”和“..”这两项。因此,cramfs中的目录的链接数通常也仅有一个。
7) cramfs中,不会保存文件的时间戳(timestamps)信息。当然,正在使用的文件由于inode保存在内存中,因此其时间可以暂时地变更为最新时间,但是不会保存到cramfs文件系统中去。
8)当前版本的cramfs只支持PAGE_CACHE_SIZE为4096的内核。因此,如果发现cramfs不能正常读写的时侯,可以检查一下内核的参数设置。
在 嵌入式的环境之下,内存和外存资源都需要节约使用。如果使用ramdisk方式来使用文件系统,那么在系统运行之后,首先要把外存(Flash)上的映像 文件解压缩到内存中,构造起ramdisk环境,才可以开始运行程序。但是它也有很致命的弱点。在正常情况下,同样的代码不仅在外存中占据了空间(以压缩 后的形式存在),而且还在内存中占用了更大的空间(以解压缩之后的形式存在),这违背了嵌入式环境下尽量节省资源的要求。
使用cramfs就是一 种解决这个问题的方式。cramfs是一个压缩式的文件系统,它并不需要一次性地将文件系统中的所有内容都解压缩到内存之中,而只是在系统需要访问某个位 置的数据的时侯,马上计算出该数据在cramfs中的位置,将其实时地解压缩到内存之中,然后通过对内存的访问来获取文件系统中需要读取的数据。 cramfs中的解压缩以及解压缩之后的内存中数据存放位置都是由cramfs文件系统本身进行维护的,用户并不需要了解具体的实现过程,因此这种方式增 强了透明度,对开发人员来说,既方便,又节省了存储空间。
我选择的文件系统是ramdsik:
要先安装mtd(memory technology device),debian中安装mtd-tools,gentoo中安装mtd-utils。
1、建立内存映像文件ramdisk
1)mkdir -p /mnt/loop
2)dd if=/dev/zero of=/tmp/loop_tmp bs=1k count=3072
3)/sbin/losetup /dev/loop0 /tmp/loop_tmp
将设备与临时文件联系起来。如果出现“ioctl: LOOP_SET_FD: 设备或资源忙”的提示,说明设备还和一文件联系,可以用/sbin/losetup /dev/loop0来看,并可用-d来删除。
4)mkfs.ext2 –m0 /dev/loop0
mkfs.ext2将会自动判断设备容量的大小并相应地配置自身,-m0参数防止它给root保留空,这样会腾出更多地有用空间。
5)mount -t ext2 /dev/loop0 /mnt/loop
6)mkdir {bin,sbin,usr,dev,etc,lib,home,opt,root,src,tmp,var,mnt,proc,sys,initrd}
7)umount /mnt/loop
卸载此文件系统,得到的/tmp/loop_tmp就是ramdisk,可以将其改名为ramdisk
8)gzip - v9 /tmp/ramdisk
在/tmp中生成一个ramdisk.gz,这样一个内存映像文件就生成了。
2、编译busybox
1)
make defconfig
make menuconfig
2)busybox设置
1>在Build Options中的Build BusyBox as a static binary (no shared libs)是问是否将busybox静态链接,如果是glibc的话不选,如果是uclibc的话要选。
2>在Installation Options选项中,默认地, 运行 make install之后, BusyBox将被安装到./_install目录。
3>NFS是肯定要选的, 使用NFS将宿主机的文件系统mount到目标板上, 这是嵌入式Linux程序开发的一个重要方面。
4>由于可使用NFS, 能在宿主机上实现的功能就都不需要在目标板上实现了。
5>Debian Utilities 全不选, Editors全不选, System Logging Utilities全不选。
6>解压缩工具只安装解压工具,gzip、bzip2、tar工具(要求目标板能解压缩tar.bz2和tar.gz文件)。
7>shell使用ash。
3)编译及安装
make TARGET_ARCH=arm CROSS=arm-linux- -j2
make install
3、用busybox给ramdisk增加命令
1)
gunzip ramdisk.gz
mount -o loop ramdisk /mnt/ramdisk
2)
cd busybox1.4.1/_install
cp -rfv * /mnt/ramdisk
umount /mnt/ramdisk
gzip -v9 ramdisk
生 成最后带有busybox命令的内存映像文件ramdisk.gz,不过此时的ramdisk文件系统内仍缺少一些必需的东西,如/lib下的库文件、 /etc下的一些配置文件、/dev下的一些块设备和文件系统等,这都需要自己添加,如果觉得麻烦,可以下载一个现成的,然后在它的基础上作一些修改。
(注:BusyBox 将数以百计的常用Unix/Linux命令集成到一个可执行文件中(名为busybox)。它体积小巧, 功能却不失强大,常用Linux命令实现的功能它都能提供,它甚至还提供了tftp, http服务程序,尽管少数的Linux命令的某些选项BusyBox没能提供, 但这并不影响它在嵌入式Linux系统中的流行。
BusyBox 可以与glibc或uClibc库进行链接编译, 可以采用动态链接或静态链接,即便采用与glibc的静态链接, 最终生成的busybox文件大小也能轻易控制在1MB之内,而采用uClibc动态链接的可执行文件就更小了,这非常适于存储空间紧张的嵌入式 Linux系统。由此, 有人将BusyBox称为嵌入式系统中的瑞士军刀,更为形象的比喻是: Linux系统中的单个命令是电路中的分立式元件, 而BusyBox是将它们集成在一起的IC: 功能不变, 体积却大为减小。)