我正在尝试使用函数 gethostbyname()
和交叉编译器 arm-none-linux-gnueabi
编译程序,但是当我运行我的二进制文件时它不起作用在安卓上。
我的代码如下:
/* gethostbyname-example.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
extern int h_errno;
int main(int argc,char **argv) {
int x, x2;
struct hostent *hp;
for ( x=1; x<argc; ++x ) {
hp = gethostbyname(argv[x]);
if ( !hp ) {
fprintf(stderr,
"%s: host '%s'\n",
hstrerror(h_errno),
argv[x]);
continue;
}
printf("Host %s : \n" ,argv[x]);
printf(" Officially:\t%s\n", hp->h_name);
fputs(" Aliases:\t",stdout);
for ( x2=0; hp->h_aliases[x2]; ++x2 ) {
if ( x2 ) {
fputs(", ",stdout);
}
fputs(hp->h_aliases[x2],stdout);
}
fputc('\n',stdout);
printf(" Type:\t\t%s\n",
hp->h_addrtype == AF_INET
? "AF_INET" : "AF_INET6");
if ( hp->h_addrtype == AF_INET ) {
for ( x2=0; hp->h_addr_list[x2]; ++x2 ) {
printf(" Address:\t%s\n",
inet_ntoa( *(struct in_addr *)
hp->h_addr_list[x2]));
}
}
putchar('\n');
}
return 0;
}
我使用 arm-none-linux-gnueabi-gcc
进行编译,在我的笔记本电脑上使用操作系统 ubuntu 12.04
和交叉编译器 Sourcery Codebench
:
$ arm-none-linux-gnueabi-gcc gethostbyname-example.c --static -o gethostbyname-example
/tmp/ccE0xjBG.o: In function `main':
lookup.c:(.text+0x38): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
$ ls
gethostbyname-example.c gethostbyname-example
$ file gethostbyname-example
gethostbyname-example: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, not stripped
然后我在我的 chroot 臂上测试二进制 gethostbyname-example
,我将二进制文件复制粘贴到 chroot
文件夹,然后我登录到 chroot
,然后我执行,顺便说一句,我从这里创建 chroot https://wiki.ubuntu.com/ARM/BuildEABIChroot ,如果我在 chroot 上运行它,我会得到如下结果:
# ./gethostbyname-example www.google.com
Host google.com :
Officially: www.google.com
Aliases:
Type: AF_INET
Address: 74.125.135.139
Address: 74.125.135.100
Address: 74.125.135.101
Address: 74.125.135.102
Address: 74.125.135.113
Address: 74.125.135.138
然后我还使用 adb push 将二进制 gethostbyname-example 上传到我的 android 设备,如果我运行二进制 gethostbyname-example,我会收到如下错误:
# ./gethostbyname-example www.google.com # Unknown server error: host 'www.google.com' # ping www.google.com # PING www.google.com (74.125.135.99) 56(84) bytes of data. # 64 bytes from ni-in-f99.1e100.net (74.125.135.99): icmp_seq=1 ttl=49 time=798 ms # 64 bytes from ni-in-f99.1e100.net (74.125.135.99): icmp_seq=2 ttl=49 time=1039 ms
在我的 android 设备中,我在/etc/和/system/etc/中有一个文件主机,带有谷歌 DNS
8.8.8.8
8.8.4.4
大概是什么原因造成的,
谢谢。
最佳答案
简短说明
glibc 中的 DNS 查找需要/lib/libnss_dns.so.2 ,这在 Android 上不可用。
另一个区别是 Android 存储 DNS 设置 /system/etc/resolv.conf
,使用仿生 C 库构建的原生 Android 应用程序将在那里寻找要查询的 DNS 服务器。使用 glibc 构建的应用程序将在 /etc/resolv.conf
中查找,这在 Android 上不存在。
更长的解释
您已经使用 glibc 构建了二进制文件,而 Android 使用仿生 C 库。
当静态链接到 libc 时,这在很大程度上应该没问题,因为我不知道 android 内核中有足够严重的变化来破坏简单的用户应用程序。不过,您应该使用 Android NDK 来构建 Android 原生应用,
然而,静态链接到 glibc 时会出现一些错误。 glibc 中的某些功能,例如为了查找用户信息、主机名和其他通常在/etc/nsswitch.conf 中配置的内容,调用其他共享库来实际完成工作。无论您是否静态链接到 glibc 本身,都会发生这种情况。这些文件通常是 glibc 系统上的/lib/libnss_* 文件。
大多数共享库都是 glibc 的一部分,并且会安装在 glibc 系统上。但它们在 Android 上不可用。当这些共享库可用时,依赖使用这些辅助共享库的函数的应用程序无法正常工作 - gethostbyname() 就是其中之一,对于正常的 DNS 查询,它需要/lib/libnss_dns.so.2
关于android - 使用函数 gethostbyname 将 C 编译为静态链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15118408/