现在的位置: 首页 > 综合 > 正文

使用busybox构建linux根文件系统

2018年04月11日 ⁄ 综合 ⁄ 共 4717字 ⁄ 字号 评论关闭

转载地址:http://blog.chinaunix.net/uid-26310563-id-3168454.html

主机:Windows XPVMware 8,Ubuntu

编译环境:arm-linux-gcc 4.4.3

Linux版本:linux-2.6.32.2

busybox版本:busybox-1.19.4

busybox源码下载地址:http://www.busybox.net/downloads/ 

参考资料:《嵌入式Linux应用开发完全手册 韦东山


所谓创建根文件系统,就是创建各种目录,并且在里面创建各种文件。比如在/bin、/sbin目录下存放各种可执行程序,在/etc目录下存放配置文件,在/lib目录下存放库文件。Busybox主要用来创建/bin、/sbin等目录下的可执行文件,如命令行下经常使用的命令ls、mv、cp等。


编译busybox

Busybox的编译较为简单,一般使用默认配置即可,如果熟悉配置选项的话也可以执行make menuconfig进行手动裁剪。具体配置说明可参考《嵌入式Linux应用开发完全手册》。

修改busybox顶层目录的Makefile文件,修改如下两行:

ARCH
 ?= arm

CROSS_COMPILE
?= arm-linux

然后执行make,编译busybox。编译完成后执行:

make CONFIG_PREFIX=/home/nfs/rootfs install

将busybox安装到目录/home/nfs/rootfs下。/home/nfs/rootfs是目标板文件系统的根目录。执行命令查看安装busybox后生成的文件:

# ls -l /home/nfs/rootfs/

drwxr-xr-x 2 root root 4096 2012-04-05 15:24 bin

lrwxrwxrwx 1 root root   11 2012-03-31 08:17 linuxrc -> bin/busybox

drwxr-xr-x 2 root root 4096 2012-03-31 08:17 sbin

drwxr-xr-x 5 root root 4096 2012-04-03 07:25 usr

linuxrc是内核启动的init进程,那内核又如何知道要启动的init进程是哪个呢?它是由uboot传递给linux内核参数中"init=xxx"决定的。在我的目标板的uboot中传递给内核的参数为"init=/linuxrc"。内核如何启动init进程可以查看内核代码init/main.c中的init_post函数。


构建lib库

虽然通过编译busybox生成了我们需要的可执行文件,但现在在目标板上仍然无法运行,需要添加lib库来支持可执行文件运行。可以使用uclibc和glibc来构建lib库。由于编译lib库相对复杂,而我们又有现成的lib库可以使用,这里我们就实行拿来主义。现成的lib库就在我们的交叉编译工具arm-linux-gcc的目录下,在本人主机上的绝对路径为/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib,

把该lib目录下的所有文件复制到目标板文件系统lib下,执行命令:

#cp -r /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib /home/nfs/rootfs/lib

PS:注意要加-r选项,把软链接文件原样复制过来,不加-r会复制软链接的链接文件,造成存储空间的浪费。


构建etc目录

创建etc/inittab参照busybox的examples/inittab文件,内容如下:


点击(此处)折叠或打开

  1. # /etc/inittab
  2. # Boot-time system configuration/initialization script.
  3. # This is run first except when booting in single-user mode.
  4. #
  5. ::sysinit:/etc/init.d/rcS
  6. # /bin/sh invocations on selected ttys
  7. #
  8. # Note below that we prefix the shell commands with a "-" to indicate to the
  9. # shell that it is supposed to be a login shell. Normally this is handled by
  10. # login, but since we are bypassing login in this case, BusyBox lets you do
  11. # this yourself...
  12. #
  13. # Start an "askfirst" shell on the console (whatever that may be)
  14. console::askfirst:-/bin/sh
  15. #tty1::askfirst:-/bin/sh
  16. # Stuff to do before rebooting
  17. ::ctrlaltdel:/sbin/reboot
  18. ::shutdown:/bin/umount -a -r

PS:这里的console是在构建/dev目录时创建的设备节点,对应的设备是启动Linux内核前传入的命令行参数“console=xxx”指定的控制台,我传递的参数为“console=ttySAC0,115200”,表示使用串口0,波特率为115200

创建etc/init.d/rcS文件。rcS是系统启动后执行的第一个脚本文件,如果想把自己编写的应用程序设置为开机启动,在本文件中中加入运行该程序的命令即可。内容如下:


点击(此处)折叠或打开

  1. #!/bin/sh
  2. ifconfig eth0 192.168.1.158
  3. mount -a


修改添加文件可执行权限:#chmod +x etc/init.d/rcS。

创建etc/fstab文件,内容如下:


点击(此处)折叠或打开

  1. #device mount-poin type options dump fsck order
  2. proc /proc proc defaults 0 0
  3. tmpfs /tmp tmpfs defaults 0 0



构建dev目录

这里使用busybox的mdev创建设备文件,mdev是udev的简化版本,它也是通过读取内核信息来创建设备文件。

要使用mdev,需要内核支持sysfs文件系统,为了减少对Flash的读写,还要支持tmpfs文件系统。先确保内核已经设置了CONFIG_SYSFS、CONFIG_TMPFS配置项。

使用mdev的命令如下,请参考它们的注释以了解其作用:

#mount -t tmpfs mdev /dev (使用内存文件系统,减少对Flash的读写)

#mkdir /dev/pts (dev/pts用来支持外部网络连接(telnet)的虚拟终端)

#mount -t devpts devpts /dev/pts

#mount -t sysfs sysfs /sys (mdev通过sysfs文件系统获得设备信息)

#echo /bin/mdev > /proc/sys/kernel/hotplug (设置内核,当有设备插拔时调用/bin/mdev程序)

#mdev -s (在/dev目录下生成内核支持的所有设备的节点)

要在内核启动后,自动运行mdev。需要修改etc目录下的两个文件:修改etc/fstab来自动挂载文件系统、修改etc/init.d/rcS加入要自动运行的命令。修改后的文件如下:


etc/fstab

点击(此处)折叠或打开

  1. #device mount-poin type options dump fsck order
  2. proc /proc proc defaults 0 0
  3. tmpfs /tmp tmpfs defaults 0 0
  4. sysfs /sys sysfs defaults 0 0
  5. tmpfs /dev tmpfs defaults 0 0


etc/init.d/rcS

点击(此处)折叠或打开

  1. #!/bin/sh
  2. ifconfig eth0 192.168.1.158
  3. mount -a
  4. mkdir /dev/pts
  5. mount -t devpts devpts /dev/pts
  6. echo /sbin/mdev > /proc/sys/kernel/hotplug
  7. mdev -s


添加mdev配置文件etc/mdev.conf,mdev.conf可以用来控制设备节点的所有者和权限,格式如下:

<device regex> <uid>:<gid> <octal permissions> 

mdev.conf还可以设置mdev在dev目录下生成的设备节点的名字,Linux内核串口驱动原本对S3C2410、S3C2440注册的设备名是s3c2410_serial0s3c2410_serial1、s3c2410_serial2,我们可以修改mdev.conf文件,使mdev在/dev目录下对应生成ttySAC0, ttySAC1和ttySAC2以符合应用程序对于串口设备操作的习惯。配置文件mdev.conf的内容如下:


    mdev.conf

点击(此处)折叠或打开

  1. # system all-writable devices
  2. full 0:0 0666
  3. null 0:0 0666
  4. ptmx 0:0 0666
  5. random 0:0 0666
  6. tty 0:0 0666
  7. zero 0:0 0666
  8. # console devices
  9. tty[0-9]* 0:5 0660
  10. vc/[0-9]* 0:5 0660
  11. # serial port devices
  12. s3c2410_serial0 0:5 0666 =ttySAC0
  13. s3c2410_serial1 0:5 0666 =ttySAC1
  14. s3c2410_serial2 0:5 0666 =ttySAC2
  15. s3c2410_serial3 0:5 0666 =ttySAC3
  16. # loop devices
  17. loop[0-9]* 0:0 0660 =loop/
  18. # i2c devices
  19. i2c-0 0:0 0666 =i2c/0
  20. i2c-1 0:0 0666 =i2c/1
  21. # frame buffer devices
  22. fb[0-9] 0:0 0666
  23. # input devices
  24. mice 0:0 0660 =input/
  25. mouse.* 0:0 0660 =input/
  26. event.* 0:0 0660 =input/
  27. ts.* 0:0 0660 =input/
  28. # rtc devices
  29. rtc0 0:0 0644 >rtc
  30. rtc[1-9] 0:0 0644
  31. # misc devices
  32. mmcblk0p1 0:0 0600 =sdcard */etc/rc.d/init.d/sd
  33. sda1 0:0 0600 =udisk * /etc/rc.d/init.d/udisk

重要的一点忘写了,希望没有误导之前看这篇文章的网友。现补充如下:

由于mdev是通过init进程来启动的,在使用mdev构造/dev目录之前,init进程至少要用到两个设备文件/dev/console/dev/null,所以要建立这两个设备文件。

# mkdir -r /home/nfs/rootfs/dev

# cd /home/nfs/rootfs/dev

# mknod console c 5 1

# mknod null c 1 3


构建其他目录

# mkdir proc mnt tmp sys root


到此,我们的根文件系统构建完毕,/home/nfs/rootfs目录下就是我们的根文件系统。目标板可以把它通过作为网络根文件系统,通过nfs直接启动。也可以把它制作为映像文件烧写到目标板的Flash启动。

抱歉!评论已关闭.