3

gethostbyname()クロスコンパイラで関数を使ってプログラムをコンパイルしようとしてarm-none-linux-gnueabiいますが、Androidでバイナリを実行すると機能しませんでした。

以下の私のコード:

  /* 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;
  }

私はでコンパイルします、OSとクロスコンパイラarm-none-linux-gnueabi-gccを備えた私のラップトップで:ubuntu 12.04Sourcery 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

次に、バイナリgethostbyname-exampleをadb pushで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/にgoogleDNSを使用したファイルホストがあります

8.8.8.8 
8.8.4.4

この失敗の原因はおおよそ何ですか、

ありがとうございました。

4

2 に答える 2

4

簡単な説明

glibc での DNS ルックアップには、Android では利用できない /lib/libnss_dns.so.2 が必要です。

もう 1 つの違いは、Android が DNS 設定 /system/etc/resolv.confを保存し、bionic C ライブラリで構築されたネイティブ Android アプリがそこを参照して、照会する DNS サーバーを見つけることです。glibc でビルドされたアプリケーションは/etc/resolv.conf、Android には存在しない を検索します。

より長い説明

glibc を使用してバイナリをビルドしましたが、Android は bionic C ライブラリを使用しています。

libc に静的にリンクする場合、これはほとんどの場合問題ないはずです。単純なユーザー ランド アプリを壊すほどの深刻な Android カーネルの変更を私は認識していないからです。ただし、Android ネイティブ アプリの構築には Android NDK を使用することになっていますが、

ただし、glibc に静的にリンクするときに問題が発生することがいくつかあります。/etc/nsswitch.conf で通常構成されているユーザー情報、ホスト名、およびその他のものを検索するための glibc の特定の関数は、実際に作業を行うために他の共有ライブラリを呼び出します。これは、glibc 自体に静的にリンクするかどうかに関係なく発生します。これらのファイルは通常、glibc システムにある /lib/libnss_* ファイルです。

これらの共有ライブラリのほとんどは glibc の一部であり、glibc システムにインストールされます。ただし、Android では利用できません。これらのヘルパー共有ライブラリを使用する機能に依存するアプリケーションは、これらの共有ライブラリが利用可能な場合に正しく動作しません - gethostbyname() はそれらの 1 つで、通常の DNS クエリでは /lib/libnss_dns.so.2 が必要です。

于 2013-02-27T18:09:53.087 に答える