进入Build Options时,不要选择Build Busybox as a static binary,其他所有操作步骤跟静态编译一样,你会发现这样建立的文件系统无法启动,终端上打印出如下消息:
Kernel panic-not synving:No init found. Try passing init=option to kernel.
为什么会出现这种问题呢?这就得回到两种编译方式的特点上来。静态编译时是将所用到的库文件一起编译了进去,而动态编译时是在需要时才调用相应的库。我们选择动态编译后,没有添加任何库文件就运行,显然是会出错的。那么如何查看busybox可执行文件里使用的库呢。ldd和Readelf都可以显示。
下面是查看cat的库的结果,linux-gate.so.1是与内核通信的,不用管。所有程序其实都是通过ld-linux.so.2来找库文件的,它就是一个中介,必不可少。
#ldd /bin/cat linux-gate.so.1 => (0x00bfe000) libc.so.6 => /lib/libc.so.6 (0x00a4a000) /lib/ld-linux.so.2 (0x00a28000)
下面是编译的ARM上的系统的库文件查找。
# arm-uclibc-linux-readelf -d busybox Dynamic section at offset 0xca014 contains 18 entries: 标记 类型 名称/值 0x00000001 (NEEDED) 共享库:[libm.so.0] 0x00000001 (NEEDED) 共享库:[libc.so.0] 0x0000000c (INIT) 0xbe24 0x0000000d (FINI) 0xb2054 0x00000004 (HASH) 0x80e8 0x00000005 (STRTAB) 0xa500 0x00000006 (SYMTAB) 0x8b70 0x0000000a (STRSZ) 3259 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0xda0cc 0x00000002 (PLTRELSZ) 3040 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0xb244 0x00000011 (REL) 0xb1bc 0x00000012 (RELSZ) 136 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x00000000 (NULL) 0x0
从上面的结果中,我们可以看到,busybox这个程序使用到了libm.so.0和libc.so.0两个库文件,实际上这是2个符号链接,分别指向libc-0.9.28.so和libuClibc-0.9.28.so。
将以上四个文件分别拷贝到lib目录下。按理说,这样应该就可以了,但是仍然无法正常运行。显示的错误信息和刚刚没加库之前一样。可能的原因有2种:一是库文件没有添加全,二是库文件没有正确被加载。
根据readelf显示的结果应该不是第一种原因。那么到底为什么没被正确加载呢?原来库文件的加载,还需要一个共享库加载器。找到对应的文件ld-uClibc-0.9.28.so和ld-uClibc.so.0添加到lib目录下后。运行正常。