介绍过交叉编译的方法,可是在使用过程中发现它的ping,traceroute以及其它的一些网络命令在使用域名作为参数时会出现
ping: bad address
traceroute: bad address
等错误,进而不能够正常工作

原因就是之前静态编译的链接于glibc上,它其中用来获取DNS信息的getaddrinfo函数在android下是有问题的,而android所使用的libc库是个google自己开发.
与glibc相比,Bionic Libc有如下一些特点:

  • 采用BSD License,而不是glibc的GPL License;
  • 大小只有大约200k,比glibc差不多小一半,且比glibc更快;
  • 实现了一个更小、更快的pthread;
  • 提供了一些所需要的重要函数,如”getprop”, “LOGI”等;
  • 不完全支持POSIX标准,比如C++ exceptions,wide chars等;
  • 不提供libthread_db 和 libm的实现

很明显getaddrinfo是POSIX的标准函数,由于并不完全支持POSIX,所以它应该有它自己的实现方法,这里不探究它如何实现,现在要做的是怎么让busybox能够使用bionic来链接。

感谢伟大的开源运动,cyanogenmod已经提供了修改好的busybox源代码,由于cyanogenmod并不兼容milestone,而它对android官方的内核以及bionic修改幅度较大所以将它的bionic完全移植过来难度还是很大的,所以这里仅仅移植一些busybox需要用到的一些函数,这样对原bionic修改幅度较小,也比较容易实现,这里说说我所修改的部分。

首先是busybox部分

cyanogenmod修改过的busybox源代码,地址在这里

将其放入android源代码的external/busybox/中

有三个文件需要修改,分别是

coreutile/df.c util-linux/mount.c util-linux/umount.c

三个文件仅需要在文件前添加

#include

即可

接下来是bionic部分

在链接过程中busybox需要是用的adjtimex,stime,swapon,swapoff,sysinfo,getsid这几个函数愿bionic中是没有的,这里要做的工作就是把这几个函数包含进syscall,需要修改或者增加的文件有:
需要添加的文件

bionic/libc/arch-arm/syscalls/adjtimex.S bionic/libc/arch-arm/syscalls/stime.S bionic/libc/arch-arm/syscalls/swapoff.S bionic/libc/arch-arm/syscalls/swapon.S bionic/libc/arch-arm/syscalls/sysinfo.S bionic/libc/arch-arm/syscalls/getsid.S

需要修改的文件

bionic/libc/arch-arm/syscalls.mk bionic/libc/include/sys/linux-syscalls.h

需要增加的那几个文件请从

获取

修改bionic/libc/arch-arm/syscalls.mk文件
在第122行syscall_src += arch-arm/syscalls/utimes.S下添加

syscall_src += arch-arm/syscalls/adjtimex.S

然后在行尾添加

syscall_src += arch-arm/syscalls/stime.S syscall_src += arch-arm/syscalls/swapon.S syscall_src += arch-arm/syscalls/swapoff.S syscall_src += arch-arm/syscalls/sysinfo.S syscall_src += arch-arm/syscalls/getsid.S

修改bionic/libc/include/sys/linux-syscalls.h文件
在第105行#define __NR_setitimer (__NR_SYSCALL_BASE + 104)后添加

#define __NR_adjtimex (__NR_SYSCALL_BASE + 124)

然后在131行#define __NR_poll (__NR_SYSCALL_BASE + 168)后添加

#define __NR_stime (__NR_SYSCALL_BASE + 25) #define __NR_swapon (__NR_SYSCALL_BASE + 87) #define __NR_swapoff (__NR_SYSCALL_BASE + 115) #define __NR_sysinfo (__NR_SYSCALL_BASE + 116) #define __NR_getsid (__NR_SYSCALL_BASE + 147)

接下来在android源代码的根目录运行
make busybox
编译好后下面这两个文件是我们所需要的
out/get/product/generic/obj/lib/libc.so
out/target/product/generic/system/xbin/busybox
获取这两个文件后,将libc.so文件拷入手机/system/lib中
busybox文件拷入/system/xbin
具体过程如下:

adb push libc.so /tmp/ adb push busybox /tmp/ adb shell su cd /tmp mount -o remount,rw /dev/block/mtdblock6 /system cp -f libc.so /system/lib/libc.so chmod 4755 /system/lib/libc.so cp -f busybox /system/xbin/busybox chmod 4755 /system/xbin/busybox mount -o remount,ro /dev/block/mtdblock6 /system exit

这里我提供一下我编译好的两个文件
注意,替换libc.so危险系数较高,我这里也就是仅仅提供一些移植cyanogenmod里面好东西思路。而以上的内容在我的手机上是能够正常工作的,如果你不在意静态编译出来的busybox的一些网络命令那就不要随便尝试了。

基于Android Bionic 库动态编译busybox

最近在基于Android做IPV6方面的开发和测试,需要使用busybox中提供的ping, ping6, nslookup, traceroute6等工具。经过测试发现:网络上介绍交叉编译busybox并放到Android中运行的文章很多,交叉编译好的busybox也可以直接下载到。但是,由于它们都是静态编译busybox并链接在标准的glibc上,导致一些功能在Android中不能正常运行,例如:#busybox ping

Android并没有采用glibc作为C库,而是采用了Google自己开发的Bionic Libc,它的官方Toolchain也是基于Bionic Libc而并非glibc的。与glibc相比,Bionic Libc有如下一些特点:

  • 采用BSD License,而不是glibc的GPL License;
  • 大小只有大约200k,比glibc差不多小一半,且比glibc更快;
  • 实现了一个更小、更快的pthread;
  • 提供了一些Android所需要的重要函数,如”getprop”, “LOGI”等;
  • 不完全支持POSIX标准,比如C++ exceptions,wide chars等;
  • 不提供libthread_db 和 libm的实现

我这里要做的就是基于bionic libc来编译busybox,以更好的提供对网络相关工具的支持。上网搜索发现,已经有一些人对busybox的移植做了许多工作,并且工作了自己的成果,比如:

  • cyanogenmod已经提供了修改好的busybox源代码下载,但是基于froyo,而且没有打开ipv6设置
  •  介绍《为Milestone/Droid动态编译busybox并连接至bionic》,但是需要修改bionic,替换libc.so

对他们的文章和源码进行了研究与尝试,可以基于cyanogenmod的源码方便的移植busybox到Android,打开ipv6相关功能,并且不需要替换libc.so。下面是我的移植步骤和经验总结:

1. 下载cyanogenmod修改过的busybox源码,并解压到/external/busybox目录

下载地址:

2. 编译busybox并修正编译错误

在Andorid源码根目录中执行: # make -j4 busybox

可能遇到的第一类编译错误如下:

  1. In file included from external/busybox/coreutils/df.c:25:  
  2. bionic/libc/include/mntent.h:48: error: expected '='','';''asm' or '__attribute__' before 'struct'  

解决方法是在出错的文件中,包含头文件stdio.h。例如在df.c中增加

  1. #include   

类似的编译出错的文件可能会有:

  1. coreutile/df.c  
  2. util-linux/mount.c  
  3. util-linux/umount.c  

可能遇到的第二类编译错误如下:

  1. external/busybox/shell/ash.c:12714: error: 'rlim_t' undeclared (first use in this function)  

出错原因是你使用的是早期的Android版本,其中rlim_t没有定义。解决方法是在/bionic/libc/include/sys/resource.h中增加

  1. typedef unsigned long rlim_t;  

可以参考Froyo中/bionic/libc/include/sys/resource.h文件。

可能遇到的第三类编译错误如下:

  1. busybox/networking/ntpd.c:1458: undefined reference to `adjtimex'  

出错原因是bionic中没有定义adjtimex,stime,swapon,swapoff,sysinfo,getsid等函数。解决方法是修改Android.mk,增加

  1. CYANOGEN_BIONIC:=true  

3. 将编译好的busybox拷贝到手机/system/xbin/目录下测试

#adb push busybox /system/xbin/

附:编译好的busybox二进制

 

Android Toolchain与Bionic Libc

Android所用的Toolchain(即交叉编译工具链)可从下面的网址下载:

。如果下载了完整的Android项目的源代码,则可以在“/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”目录下找到交叉编译工具,比如Android所用的arm-eabi-gcc-4.2.1

Android并没有采用glibc作为C库,而是采用了Google自己开发的Bionic Libc,它的官方Toolchain也是基于Bionic Libc而并非glibc的。这使得使用或移植其他Toolchain来用于Android要比较麻烦:在Google公布用于Android的官方Toolchain之前,多数的Android爱好者使用的Toolchain是在 下载的一个通用的Toolchain,它用来编译和移植Android Linux内核是可行的,因为内核并不需要C库,但是开发Android的应用程序时,直接采用或者移植其他的Toolchain都比较麻烦,其他Toolchain编译的应用程序只能采用静态编译的方式才能运行于Android模拟器中,这显然是实际开发中所不能接受的方式。目前尚没有看到说明成功移植其他交叉编译器来编译Android应用程序的资料。

glibc相比,Bionic Libc有如下一些特点:

-          采用BSD License,而不是glibcGPL License

-          大小只有大约200k,比glibc差不多小一半,且比glibc更快;

-          实现了一个更小、更快的pthread

-          提供了一些Android所需要的重要函数,如”getprop”, “LOGI”等;

-          不完全支持POSIX标准,比如C++ exceptionswide chars等;

-          不提供libthread_db  libm的实现

 

另外,Android中所用的其他一些二进制工具也比较特殊:

-          加载动态库时使用的是/system/bin/linker而不是常用的/lib/ld.so;

-          prelink工具不是常用的prelink而是apriori,其源代码位于/build/tools/apriori”

-          strip工具也没有采用常用的strip,即“/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”目录下的arm-eabi-strip,而是位于/out/host/linux-x86/bin/soslim工具。

 

网址:

http://blog.csdn.net/codejoker/archive/2010/08/25/5837456.aspx

http://blog.csdn.net/TopEmbedded/archive/2008/12/10/3492649.aspx