1.Busybox
1、配置busybox
busybox的配置程序和linux内核菜单配置方式简直一模一样.熟悉用make menuconfig方式配置linux内核的朋友很容易上手.
#cp busybox-1.00.tar.gz /babylinux
#cd /babylinux
#tar xvfz busybox-1.00.tar.gz
#cd busybox-1.00
#make clean ;清除旧的编译文件
#make menuconfig
下面是需要编译进busybox的功能选项。
General Configuration应该选的选项
Show verbose applet usage messages
Runtime SUID/SGID configuration via /etc/busybox.conf
Build Options
Build BusyBox as a static binary (no shared libs)
这个选项是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使它正常工作.
Do you want to build busybox with a cross complier?
这个选项是询问你是否需要用交叉编译器生成busybox,如果需要就选中,并在Cross compiler prefix中输入做好的toolchain的bin路径,例如:/root/rm300/tools/buildroot/build_armeb/bin/armeb-linux-,注意最后是armeb-linux-,不能加其他字符或空格。
在Any extra CFLAGS options 中输入做好的toolchain下的include路径,例如:/root/rm300/tools/buildroot/build_armeb/include
Installation Options
Don't use /usr
这个选项也一定要选,否则make install 后busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令.选择这个选项后,make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向它的链接.
再根据系统需要,进入所需命令工具所在的子菜单中,选择相应的命令项。如需要“insmod”命令,就在“Linux Module Utilities”子菜单中选中。 其它选项都是一些linux基本命令选项,自己需要哪些命令就编译进去,一般用默认的就可以了,配置好后退出并保存。
注意:执行完make menuconfig后,在目录下会生成一个.config文件,可以通过 #ls -l .config来查看,为了将来编译出一样的busybox我们需要保存此次配置,可以把该配置文件保存为busybox_defconfig,即 #cp .config busybox_defconfig.下次执行时,之需要#cp busybox_defconfig .config,不需要再执行make menuconfig。
2、编译并安装busybox
#make
#make install
编译好后在busybox目录下生成子目录_install,里面的内容:
drwxr-xr-x 2 root root 4096 11月 24 15:28 bin
rwxrwxrwx 1 root root 11 11月 24 15:28 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 11月 24 15:28 sbin
其中可执行文件busybox在bin目录下,其他的都是指向他的符号链接
如果是用交叉编译工具链编译的则会生成bin sbin usr/bin usr/sbin几个目录,可以把这几个目录复制到你做好的rootfs目录下。
2.建立根文件系统
1、建立目录
构建工作空间时,rootfs文件夹用来存放根文件系统,
#cd rootfs
根据根文件系统的基本结构,建立各个对应的目录:
# mkdir bin dev etc lib proc sbin tmp usr var root home
# chmod 1777 tmp
# mkdir usr/bin usr/lib usr/sbin
# ls
dev etc lib proc sbin tmp usr var
# mkdir var/lib var/lock var/log var/run var/tmp
# chmod 1777 var/tmp
对于单用户系统来说,root和home并不是必须的。
准备好根文件系统的骨架后,把前面建立的文件安装到对应的目录中去。
2、拷贝链接库
把建好的toolchain目录下的lib目录下的库文件即uclibc的库文件拷贝到刚才建立的lib文件夹中:
# cd ${PREFIX}/lib
[root@skynet lib]# cp *.so ${PRJROOT}/rootfs/lib
[root@skynet lib]# cp -d *.so.[*0-9] ${PRJROOT}/rootfs/lib
3、添加基本的应用程序
系统的应用程序,基本上可以分为三类:
基本系统工具,如ls、ifconfig这些……
一些服务程序,管理工具,如WEB、Telnet……
自己开发的应用程序
这里先添加基本的系统工具,有想过把这些工具的代码下载下来交叉编译,不过实在是麻烦,用BusyBox,又精简又好用……,可以参考上一篇文章busybox,编译完成后可以直接把bin sbin usr这3个文件夹拷贝到roorfs目录下替代原来的目录。
initrd的简单介绍及根文件系统的挂载
initial RAM disk Linux® 初始 RAM磁盘(initrd)是在系统引导过程中挂载的一个临时根文件系统,用来支持两阶段的引导过程。initrd文件中包含了各种可执行程序和驱动程序,它们可以用来挂载实际的根文件系统,然后再将这个 initrd RAM 磁盘卸载,并释放内存。在很多嵌入式Linux 系统中,initrd 就是最终的根文件系统。本文将探索 Linux 2.6 的初始 RAM 磁盘,包括如何创建以及如何在Linux 内核中使用。
什么是初始 RAM 磁盘
初始 RAM磁盘(initrd)是在实际根文件系统可用之前挂载到系统中的一个初始根文件系统。initrd与内核绑定在一起,并作为内核引导过程的一部分进行加载。内核然后会将这个 initrd文件作为其两阶段引导过程的一部分来加载模块,这样才能稍后使用真正的文件系统,并挂载实际的根文件系统。
使用初始 RAM 磁盘来引导系统(比较老了,和当前的流程有差别!!)
在内核和 initrd映像被解压并拷贝到内存中之后,内核就会被调用了。它会执行不同的初始化操作,最终您会发现自己到了init/main.c:init()函数中
根文件系统的挂载过程
1、VFS注册
2、VFS挂载
3、根文件系统的挂载
default_rootfs()主要往rootfs中生成两个目录/dev和/root以及一个设备文件/dev/console。似乎在rootfs中的init文件必须位于根目录下,即/init,否则系统会尝试mount其他的文件系统。
populate_rootfs()如果内核支持initrd,但并没有配置CONFIG-INITRAMFS_SOURCE选项的话,内核在编译的时候会自动生成一个最小的cpio包附在内核中,这个自带的cpio包的内容与default_rootfs生成的一样。
cpio包类型的initrd被填充到rootfs中去,接下来初始化ramdiak_execute_command,这个变量表示在cpio包中被执行的第一个程序,可通过在内核启动参数中给rdinit=赋值来确定。接下来检查在rootfs中是否存在变量ramdisk_execute_command所指的文件。如果有,就说明cpio包类型的initrd成功加载了,那就不需要内核再调用prepare_namespace()来挂载根文件系统,这些都留给cpio包中的ramdisk_execute_command所指的程序去完成。如果没有,就说明内核没有成功用上cpio包类型的initrd,还需要调用prepare_namespace()来继续准备加载根文件系统,并清空变量ramdisk_execute_command。无论怎样,内核都会继续执行init_post.
在init_post中调用run_init_process,会依次执行指定的init文件,如果失败,就会执行/sbin/init, /etc/init,, /bin/init,/bin/sh。注意的是,run_init_process在调用相应程序运行的时候,用的是kernel_execve。也就是说调用进程会替换当前进程。只要上述任意一个文件调用成功,就不会返回到这个函数。如果上面几个文件都无法执行。打印出没有找到init文件的错误。