构建Linux根文件系统(未完待续)

      所谓制作根文件系统, 就是创建各种目录, 并且在里面创建各种文件。 比如在/bin 、/sbin 目录下存放各种可执行程序, 在/etc 目录下存放配置文件, 在/lib 目录下存放库文件。

第一步:Busybox的配置、编译和安装

Busybox概述

    Busybox的官方网站是http://www.busybox.net/,源码可以从http://www.busybox.net/ downloads/下载    

    Busybox 将众多的 UNIX 命令集合进一个 很小的可执行程序中, 可以用来替换 GNU fileutils 、 shellutils 等工具集。它的各种命令 与相应的 GNU 工具相比,所能提供的选项较少, 但是能够满足一般应用。 Busybox 为各种小 型的或者瞅入式系统提供了一个比较完全的工具集。Busy box 在编写过程中对文件大小进行优化, 并考虑了系统资源有限(比如内存等)的情况。与一般的GNU工具集动辄几如侣的体积相比,动态连接的Busybox只有几百KB,即使静态连接也只街IMB左右。Busybox按模块进行设计,可以很容易地加入、去除某些命令, 或增减命令的某些选项。

       Busy box支持uClibc库和glibc库,对Linux2.2.x之后的内核支持良好。在创建一个最小的根文件系统时,使用Busybox的话,只需要在/dev目录下创建必要的 设备节点、在/etc目录下创建一些配置文件就可以了,如果Busybox使用动态连接,还要在/lib 目录下包含库文件。

linux内核启动第一个用户进程的过程

   先来回顾下linux内核启动第一个用户进程的过程:函数调用关系为:start_kernel() -> rest_init() -> kernel_thread() -> kernel_init()。在 kernel_init()中

        1)它首先会调用kernel_init_freeable()函数,打开标准输入、标准输出、标准错误设备。该函数中的:

第一行尝试打开/dev/console设备文件,如果成功,它就是init进程标准输入设备。
第二行和第三行将文件描述符0复制给文件描述符1、2,所以标准输入、标准输出、标准 错误都对应同-个文件(设备)。

从这点也不难看出:在内移植Linux内核时,如果发现打印出“Warning:unable to open an initial console.”,其 原因大多是:根文件系统虽然被正确挂接了,但是里面的内容不正确,要么没有/dev/console这个文件,耍么它没有对应的设备。

 注:Linux中最先打开的3个文件分别称为标准输入(stdin)、标准输出(stdout)、标准错误(stderr),它们对应的文件描述符:分别为0、1、2。所谓标准输入就是在程序中使用scant'()、 fscanf(stdin,…)获取数据时,从哪个文件(设备)读取数据:标准输出、标准错误都是输出设备,前者对应printf()、fprintf(stdout, · · ·),后者对应fprintf(stderr,…)

    2)调用run_init_process(ramdisk_execute_command)函数。如果ramdisk_execute_ command变量指定了要运行的程序,启动它。

    3)调用run_init_process(execute_command)函数。如果execute_command变量指定了要运行的程序,启动它。

    4)调用try_to_run_init_process()函数。依次尝试执行 /sbin/init、/etc/init、/bin/init、/bin/sh。

最终会根据参数选择创建一个用户进程,从此系统的控制权交给该用户进程(一旦创建进程成功,它将不会返回),比如选择/sbin/init这个程序作为init进程的执行程序,也即内核启动的第一个(也是惟一的一个)用户进程(进程ID为I),它根据配 置文件(/etc/inittab)决定启动哪些程序,比如执行某些脚本、启动shell、运行用户指定的程序等。init进程 是后续所有进程的发起者,比如init进程启动/bin/sh程序后,才能够在控制台上输入各种命令。当然我们也完全可以编写自己的/sbin/init程序,或者传入命令行参数”init = xxxxxxx"指定某个程序作为init进程运行。

Busybox init进程的启动过程

    Busybox init程序对应的代码在init/init.c文件中,下面以busybox-1.21.1为例。先概述其流程,再结合一个/etc/inittab文件讲述init进程的启动过程。
     1)Busybox init程序流程如下图所示,其中与构建根文件系统关系密切的是控制台的初始化、对inittab文件的解释及执行。

        内核启动init进程时已经打开“/dev/console”设备作为控制台,一般情况下Busybox init 程序就使用/dev/console。但是如果内核启动init进程的同时设置了环境变量CONSOLE或 console,则使用环境变量所指定的设备。在Busybox init程序中,还会检查这个设备是否可以打开,如果不能打开则使用“/dev /null”。
        Busybox init进科只是作为其他进程的发起者和控制者,并不需要控制台与用户交互,所 以init进程会把它关掉,系统启动后运行命令“Is/proc/1/fd/”可以看到该目录为空。init进 程创建其他子进程时,如果没有在/etc/inittab中指明它的控制台,则使用前面确定的控制台。
       /etc/inittab文件的相关文档和示例代码都在Busybox的examples/inittab文件中。
      如果存在/etc/inittab文件,Busyboxinit程序解析它,然后按照它的指示创建各种子进程: 否则使用默认的配置创建子进程。
        /etc/inittab文件中每个条自用来定义一个子进程,并确定它的启功方法,格式如下:

<id_>: <runlevels>: <action>: <process>   例如 ttySAC0::askfirst : -/bin/sh     对于Busybox init程序,前述各个字段作用如下。

        <id>:表不这个子进程要使用的控制台(即标准输入、标准输出、标准错误设备)如果省略,则使用与init进程一样的控制台。

        <run levels>:对于Busybox init程序,这个字段没有意义,可以省赂。

        <action>:表示init进程如何控制这个子进程,有下表所示的8种取值。

         

        <process>:要执行的程序,它可以是可执行程序,也可以是脚本。 如果<procss>字段前有“-“字符,这个程序被称为“交互的”。

         在/etc/inittab文件的控制下,init进程的行为总结如下,

      在系统启功前期,init进程首先启动<action>为sysinit、wait、once的3类子i进程。
      在系统市常运行期间, init进程首先启动<action>为respawn、askfirst的两类子进程,并监视它们,发现某个子进程退出时重新启动它。

      在系统退出时,执行<action>为shutdown、restart、ctrlaltdel的3类子进程(之一或全部)。

       如果根文件系统中没有/etc/inittab文件,Busybox init程序将使用如下默认的inittab条目。

        

    2)/etc/inittab实例。

     仿照Busybox的examples/inittab文件, 创建一个inittab文件,内容如下:

     

配置编译安装Busybox

     1)配置

      Busybox集合了几百个命令,在一般系统中并不需要全部使用。可以通过配置Busybox 来选择这些命令、定制某些命令的功能(选项)、指定Busybox 的连接方法(动态连接还是静态连接)、 指定 Busybox 的安装路径(也可以在安装时通过命令指定)。在 busybox-l.21.1 目录下执行 “ make menuconfig” 命令即可进入配置界面,按照自己的需求配置好后,退出保存即可。Busybox的配置过程大多是选择、去除各种命令,一目了然。

    2)编译和安装

       编译前先修改 Busybox 根目录的 Makefile. 使用交叉编译器(修改ARCH和CROSS_COMPILE),执行make来编译;

      最后是安装,执行 “ make CONFIG_PREFIX=dir_path install“ , 就可以将Busybox安装在 dir_name指定的目录下。一切完成之后,将在dir_path目录下生成

         三个目录:bin、sbin、和usr

        一个文件:linuxrc (通过ls linux -l命令可知它指向bin/busybox)

        其中linuxrc和上面分析的/sbin/init程序功能完全一样:其他目录下是各种命令, 不过它们都是到/bin/busybox的符号连接,比如到/sbin目录下,执行ls -l发现每个文件都指向bin/busybox。由此可见此时除bin/busybox外, 其他文件都是到bin/busybox的符号连接。busybox是所有命令的集合体, 这些符号连接文件可以直接接运行。比如在开发板上,运行 “ Is” 命令和 “ busybox ls” 命令是 一样的。

第二步:使用glibc库

 制作交叉编译工具链时,已经生成了glibc库,可以直接使用它来构建根文件系统:在dir_path下创建lib目录,将需要用到的库拷贝进去。

第三步:构建根文件系统(未完待续)

 

原文地址:https://www.cnblogs.com/zhangshuaifeng/p/10130812.html