天天看点

busybox初探

一、busybox是什么?

     (1)busybox是Linux上的一个应用程序(application)。

     (2)它整合了许多Linux上常用的工具和命, 如rm, ls, gzip, tftp等。对于这些工具和命令,busybox中的实现可能不是最全的,但却是最常用的,因此它的特点就是短小精悍,特别适合对尺寸很敏感的嵌入式系统。

     (3)busybox的官方网站是http://www.busybox.net/,在这里你可以找到与busybox相关的所有资料。

二、busybox的下载

       最新的busybox的源码更新都可以在http://www.busybox.net/downloads/ 里面找到。

三、Busybox目录结构简介

busybox初探

四、Busybox中最重要的程序:init进程

(1)Busybox init在嵌入式系统中的应用

         大家都知道init进程是由内核启动的第一个(也是唯一一个)用户进程(进程ID为1),init进程根据配置文件决定启动哪些程序,例如:执行某些脚本、启动shell或运行用户程序等等。

         由于BusyBox自身的一些特点,BusyBox init非常适合在嵌入式系统开发中使用,被誉为“嵌入式linux的瑞士军刀”。 在嵌入式系统中常使用的也是Busybox集成的init程序,通过定制可以将其做得非常精炼。

(2)init的执行流程

        移植uboot的目的是启动内核,启动内核的目的是运行应用程序,从内核的启动流程中可以知道内核启动的第一个应用程序就是busybox里的/sbin/init进程!

        但是我们的最终目的不是启动init进程,而是运行客户的程序!

        那么init进程是如何选择性的运行客户的程序呢?我们猜测init进程肯定需要:

      (1) 读取一个配置文件

      (2) 解析该配置文件

      (3) 根据配置文件执行客户的程序

接下来分析busybox中init程序的源码,看看我们上述猜测的流程是否相同。

由于init_main很长,所以我们简化其代码,就流程中的几个重点部分代码进行分析:

init_main()在init/init.c的中,以下按照重点代码顺序依次分析:

1.在设置信号后,初始化/dev/console

console_init();
           

2.读取配置文件,并解析它

if (argv[1]
&& (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
	) {
		new_init_action(RESPAWN, bb_default_login_shell, "");
	  }
     else {
		parse_inittab();
	  }
           

 因为内核启动/sbin/init是没有传如何参数,所以上述程序进入parse_inittab()函数。

我们进入到parse_inittab()函数:

首先遇到的是这段程序: 

parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
           

由此可以知道init进程读取的配置文件就是/etc/inittab,busybox中的inittab文件中规定了/etc/inittab内容的填写格式如下: 

<id>:<runlevel>:<action>:<process>

Id:id会加上一个/dev前缀作为一个控制终端(stdin,stdout,stderr)

Runlevel:忽略

Action:执行的时机,包括SYSINIT,WAIT,ONCE, RESPAWN,ASKFIRST等

Process:要执行的应用程序或者脚本

接着继续分析 parse_inittab()剩余的程序:

if (parser == NULL)
{
     new_init_action(SYSINIT, INIT_SCRIPT, "");
     new_init_action(ASKFIRST, bb_default_login_shell, "");
     new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
     new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
     new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
     new_init_action(CTRLALTDEL, "reboot", "");
     new_init_action(SHUTDOWN, "umount -a -r", "");
     new_init_action(SHUTDOWN, "swapoff -a", "");
     new_init_action(RESTART, "init", "");
		
     return;
}
           

如果配置文件/etc/inittab不存在的话则执行if语句,也就是说如果没/etc/inittab的话init进程会直接调用new_init_action来构造默认配置项,根据if语句里的内容,我们可以反推出等效的/etc/inittab的内容如下: 

::SYSINIT:/etc/init.d/rcS

::ASKFIRST:-/bin/ah

tty2:: ASKFIRST:-/bin/sh

tty3:: ASKFIRST:-/bin/sh

tty4:: ASKFIRST:-/bin/sh

::CTRLALTDEL:reboot

::SHUTDOWN:umount -a –r

::RESTART:init

这里 new_init_action()函数是配置的核心,其主要作用是将/etc/inittab里的每一条配置项做成一个init_action结构体并添加到具有相同执行时机的init_action_list中去,最终将它们连接成单链表。

也就是说解析/etc/inittab这个配置文件就是为了把各配置项添加到对应的init_action_list中去。

到这里,parse_inittab()这个函数就结束了,我们继续回到init_main()这个函数的分析。

3.运行parse_inittab()帮我们添加到init_action_list中的程序或脚本

run_actions(SYSINIT);
    run_actions(WAIT);
    run_actions(ONCE);
    while (1) 
    {
        run_actions(RESPAWN);
        run_actions(ASKFIRST);
    }
           

run_actions为运行一类程序或脚本,这里的一类就是按照执行时机来分类的。

总结上述对于init_main()函数的分析,我们看到init进程的执行流程与我们猜测的基本相同。init进程起来后,首先会去读取/etc/inittab配置文件,如果没/etc/inittab的话init进程会直接调用new_init_action来构造默认配置项;然后解析这个配置文件,将/etc/inittab里的每一条配置项做成一个init_action结构体并添加到具有相同执行时机的init_action_list;最后,根据init_action_list来运行其中的程序和脚本。

五、busybox的配置、编译和安装

在busybox的INSTALL文件已经说明我们应该如何配置、编译和安装busybox。

Building:

=========

The BusyBox build process is similar to the Linux kernel build:

  make menuconfig     # This creates a file called ".config"

  make                # This creates the "busybox" executable

  make install        # or make CONFIG_PREFIX=/path/from/root install

The full list of configuration and install options is available by typing:

  make help

文件中写的很明确,编译busybox和编译linux kernel差不多。即首先要make menuconfig生成配置文件.config。然后make生成busybox可执行文件。最后make install安装busybox。

第一步,执行 make menuconfig: 

busybox初探

执行过后会出现图形界面,这方便了我们对busybox的配置,这里我们只需要手动选择需要编译安装的项目,最后进行保存就可以了。最后Exit,save即可。

第二步,执行make命令生成可执行busybox文件。

第三步,make install进行安装。

这样,经过简单的配置、编译和安装我们便可以使用busybox了。

关于busybox的配置、编译和安装可以详细参考博客:     busybox详解 中的构造自己的根文件系统部分。

六、关于busybox的使用

busybox的使用很简单,有以下三种方式:

(1)   busybox后直接跟命令,如

       busybox ls

       busybox tftp

(2)   直接将busybox重命名,如

       cp busybox tftp

       cp busybox tar

       然后再执行tftp, tar  

(3)  创建符号链接(symbolic link), 如

       ln -s busybox rm

       ln -s busybox mount

       然后就可以执行rm,mount等

继续阅读