当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
为linux内核构建最小的根文件系统
发布时间:2010/6/29 13:32:21 来源:城市学习网 编辑:ziteng
  linux内核init进程函数的部分代码如下:
  01 if (execute_command)
  02 run_init_process(execute_command);
  03
  04 run_init_process("/sbin/init");
  05 run_init_process("/etc/init");
  06 run_init_process("/bin/init");
  07 run_init_process("/bin/sh");
  08
  09 panic("No init found. Try passing init= option to kernel.");
  10 }
  代码中我们看出,linux内核在初始化的最末段,也就是挂载了跟文件系统之后,开始了与根文件系统,也就是用户应用的沟通,我们看到:内核分别尝试了/sbin/init, /etc/init, /bin/init, /bin/sh四个应用的执行,由此可以想到,只要我们准备相应的应用,并且只要满足其中之一,就可以启动系统了,如果任何的一个都没有满足,那么久会出现很经典的内核panic:No init found. Try passing init= option to kernel.
  在此,我们利用现有分析,构建一个可以说是很小的根文件系统,busybox是针对嵌入式开发需求,集各种unix工具于一身的很小很强大的工具集。busybox的编译过程不再赘述,现假设busybox编译后已经生成如下文件夹:
  bin linuxrc sbin usr
  其中,linuxrc为程序,bin、sbin、usr为文件夹,其实三个文件夹内绝大部分是程序,并且是指向bin/busybox的链接,也就是所有的命令均由bin/busybox执行
  我们看到,内核初始化最后一次尝试的bin/sh, 猜想上来sh并不会跟其它的程序产生关联,所以干脆删除sbin和usr再说,同时linuxrc似乎也不是必须,最多内核报告错误,并不会产生panic,所以精简后,根目录如下(有点裸了:)):
  bin
  呵呵,现在想,估计是启动不起来的,为什么呢?起码sh程序或者说busybox要依赖一些动态库,当然可以编译选择静态编译了,那么似乎连什么库都不要,但是我们这里说的最小,并不是文件最少,而是最必须的意思,同时默认busybox编译,采用动态库,所以无论怎么说,lib库是最小根文件系统必须的。所以,添加lib目录,其中的动态库文件来自交叉编译器的lib目录。现在的最小根文件系统如下:
  bin lib
  这时候,先别急,我们发现bin目录下,仍然有很多文件,当然也是链向bin/busybox的链接,也就是说,有没有他们没什么关系,那么如果删除他们也没什么影响咯,开始精简bin目录,精简后目录如下:
  busybox sh
  sh程序(到busybox的链接),以及busybox,现在发现,直接输入rm等命令已经不管用了,那么是不是意味着我们的精简结束了呢?因为诸如rm这样的命令只是一个指向busybox的链接,那么就是说我们直接busybox rm这样调用,也可以使用咯,测试一下,果然好用。现在bin目录做到了最小 [NextPage]   回顾一下,我们现在的根文件系统目录如下:其中,bin目录已经最小,下面看看lib目录有没有什么压缩的空间。
  bin lib
  lib目录之所以保留到现在,是因为总是怀疑busybox可能用到这个那个库的,所以看看busybox到底用到些什么动态库,pc上执行命令arm-linux-gcc -d busybox,看到以下结果:
  01 Dynamic section at offset 0xb5014 contains 22 entries:
  02   Tag        Type                         Name/Value
  03 0x00000001 (NEEDED)                     Shared library: [libcrypt.so.1]
  04 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
  05 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
  06 0x0000000c (INIT)                       0xc18c
  07 0x0000000d (FINI)                       0x9e8dc
  08 0x00000004 (HASH)                       0x80e8
  09 0x00000005 (STRTAB)                     0xa410
  10 0x00000006 (SYMTAB)                     0x8b40
  11 0x0000000a (STRSZ)                      3410 (bytes)
  12 0x0000000b (SYMENT)                     16 (bytes)
  13 0x00000015 (DEBUG)                      0x0
  14 0x00000003 (PLTGOT)                     0xc50ec
  15 0x00000002 (PLTRELSZ)                   3040 (bytes)
  16 0x00000014 (PLTREL)                     REL
  17 0x00000017 (JMPREL)                     0xb5ac
  18 0x00000011 (REL)                        0xb55c
  19 0x00000012 (RELSZ)                      80 (bytes)
  20 0x00000013 (RELENT)                     8 (bytes)
  21 0x6ffffffe (VERNEED)                    0xb47c
  22 0x6fffffff (VERNEEDNUM)                 3
  23 0x6ffffff0 (VERSYM)                     0xb162
  24 0x00000000 (NULL)                       0x0
 [NextPage]   我们发现,busybox只使用了libcrypt.so.1 libm.so.6 libc.so.6三个共享库,所以马上精简lib库,考虑可以留下的库文件,以上三个是必须的,那么还有没有必须的呢?经过试验,我们发现,除了上边的 3个库以外,ld-linux.so.2不能缺少,猜想可能用于装在,毕竟ld~load,呵呵!到此,lib库精简完成。
  这时候,会有人问,那么是不是现在的根文件系统已经可以被挂载,并且最小了呢?现在可以重启开发板了,此时busybox reboot命令已经不能使用,具体原因看输出就知道,重启,下面是结果:
  01 Kernel panic - not syncing: Attempted to kill init!
  02 Backtrace:
  03 [<c002b600>] (dump_backtrace+0x0/0x10c) from [<c002b740>] (dump_stack+0x18/0x1c)
  04
  05 r6:00000000 r5:c3812c40 r4:c3816000
  06 [<c002b728>] (dump_stack+0x0/0x1c) from [<c003d038>] (panic+0x48/0x11c)
  07 [<c003cff0>] (panic+0x0/0x11c) from [<c003f348>] (do_exit+0x64/0x59c)
  08 r3:c0349c50 r2:c38194e0 r1:c3817f2c r0:c02fcf60
  09 r4:c3816000
  10 [<c003f2e4>] (do_exit+0x0/0x59c) from [<c003f910>] (do_group_exit+0x90/0xc4)
  11 [<c003f880>] (do_group_exit+0x0/0xc4) from [<c003f95c>] (sys_exit_group+0x18/0x2
  12 0)
  13 r4:000c622c
  14 [<c003f944>] (sys_exit_group+0x0/0x20) from [<c0027da0>] (ret_fast_syscall+0x0/0
  15 x2c)
  结果是不是算灾难性的?至少系统启动失败了!经过无数次烧写文件系统,逐步rm文件,发现console设备文件是必须的,至少bin/sh启动需要,所以添加dev/console,最终的最小根文件系统如下:
  1 root@root:/home/works/rootfs_least# ls
  2 bin dev lib
  3 root@root:/home/works/rootfs_least# ls bin
  4 busybox sh
  5 root@root:/home/works/rootfs_least# ls dev
  6 console
  7 root@root:/home/works/rootfs_least# ls lib
  8 ld-linux.so.2 libcrypt.so.1 libc.so.6 libm.so.6
  9 root@root:/home/works/rootfs_least#
  好了,最小的根文件系统已经做好了!方法是:rm reboot rm reboot……分析原因,总结!期待下一篇:为linux内核构建最小的根文件系统-一步一步添加~
广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved