2013-03-01 24 views
12

Làm thế nào để giải quyết biên dịch một nhị phân tĩnh mà mã bao gồm một chức năng GetHostByName và nếu biên soạn mà không cần cảnh báo như thế này:Biên soạn một nhị phân tĩnh mà mã có một chức năng GetHostByName

cảnh báo: Sử dụng 'GetHostByName' trong các ứng dụng liên kết tĩnh đòi hỏi trong thời gian chạy các thư viện được chia sẻ từ các phiên bản glibc sử dụng để liên kết

tôi biên dịch trên ubuntu 12.04 với lệnh:

$ gcc -static lookup.c -o lookup 

Đây là mã cho lookup.c:

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

tôi muốn nếu tôi kiểm tra qua $ file lookup sẽ nhận được kết quả như thế này:

tra cứu: ELF 32-bit LSB thực thi, Intel 80386 , phiên bản 1 (GNU/Linux), liên kết tĩnh, cho GNU/Linux 2.6.24, BuildID [sha1] = 0x6fcb2684ad8e5e842036936abb50911cdde47c73, chưa bóc

Không thích này:

tra cứu: ELF 32-bit LSB thực thi, Intel 80386, phiên bản 1 (SYSV), (libs sử dụng được chia sẻ) liên kết động, cho GNU/Linux 2.6.24, BuildID [ sha1] = 0xf9f18671751927bea80de676d207664abfdcf5dc, chưa bóc

Nếu bạn nhận xét với đề nghị tôi phải sử dụng mà không tĩnh vì libc khác nhau mỗi linux tôi biết điều đó, tôi hy vọng bạn không cần phải bình luận. Tại sao tôi vẫn tồn tại trong tĩnh? Vì ở đó tôi cần phải thực hiện các tệp nhị phân tĩnh, bắt buộc phải tĩnh và không động.

Tôi có hơn 2 tuần tìm kiếm điều này nhưng cho đến nay vẫn chưa thành công.

Cảm ơn bạn đã giúp tôi giải quyết vấn đề nặng nề của mình.

+2

Tóm lại: không liên kết tĩnh một chương trình như vậy. Liên kết nó theo cách động, như thường lệ, với 'libc.so' –

+0

Hello Basile của bạn. Tại sao? –

+0

Cách thực hiện? cái gì với -Bdynamic -lc -Wl? –

Trả lời

22

Điều bạn đang yêu cầu sẽ rất khó khăn.

Xem this StackOverflow question about getaddrinfo. Về cơ bản, bên dưới getaddrinfo/gethostbyname là lớp NSS của glibc. Điều này cho phép sysadmin nói "sử dụng DNS để phân giải tên máy chủ thành địa chỉ IP" hoặc "sử dụng LDAP" hoặc "không sử dụng bất kỳ thứ gì khác ngoài /etc/hosts". Điều khiển này là lúc chạy; sysadmin có thể thay đổi cách hostname được phân giải thành IP.

Vì tính linh hoạt này, tất cả các cuộc gọi có độ phân giải tên trong thư viện trợ giúp sử dụng glibc (plugin, về cơ bản) để thực hiện công việc giải quyết grunt. Có một thư viện được chia sẻ cho địa chỉ LDAP, một cho tệp, một cho DNS, một cho YP, v.v. v.v.

Nếu bạn muốn chương trình của bạn được liên kết tĩnh 100%, bạn sẽ phải đi nơi khác (KHÔNG gethostbyname) để chuyển đổi tên máy chủ thành địa chỉ IP.Bạn có thể làm điều này với một thư viện giải quyết như uDNS (không phải chính xác này - có sẵn các công cụ tương tự), nhưng bạn nên nhớ rằng nhị phân của bạn sẽ không làm điều đúng trên các hệ thống được định cấu hình không sử dụng DNS!

Thay vào đó, tôi khuyên bạn nên chỉ rời khỏi chương trình (về mặt kỹ thuật) được liên kết động. Nếu bạn thực sự muốn chắc chắn rằng nó sẽ chạy trên bất kỳ nền tảng nào, thậm chí bạn có thể gửi glibc với hệ nhị phân - mặc dù thực hiện điều này sẽ yêu cầu sự phù hợp của LGPL. Việc rời khỏi liên kết động này tại chỗ sẽ chỉ có nghĩa là bạn sẽ không hoạt động trên các hệ thống với phiên bản glibc sai - không phải là vấn đề tương thích lớn.

Nói về việc tuân thủ giấy phép, nó có giá trị lưu ý rằng nếu bạn tĩnh liên kết glibc, nhiều khả năng bạn có để vận chuyển các mã nguồn cho toàn bộ ứng dụng của bạn tuân thủ giấy phép LGPL glibc 's. Tôi không phải là luật sư và đây không phải là tư vấn pháp lý đủ điều kiện, nhưng việc đọc LGPL làm cho nó rất rõ ràng rằng các ứng dụng liên kết tĩnh glibc phải là nguồn mở. Xem this StackOverflow question on the topic.

+0

Xin chào Borealid cảm ơn vì đề xuất của bạn, tôi sẽ tiếp nhận đầu tiên. –

+3

+1 cho giấy phép nhắc nhở về LGPL trong libc. Lưu ý rằng một số libc-s không phải là LGPL mà là MIT ví dụ http://musl-libc.org/ –

+4

Được giải quyết bằng musl-libc. Tôi biên dịch mul-libc và sau đó tôi biên dịch chương trình của tôi sử dụng thư viện musl-libc với lệnh -L/path/tomuslcompiled/lib. Tôi rất hạnh phúc, Cảm ơn ông Borealid –

0

Tôi có 2 câu trả lời -

  1. Giữ phần chính của chương trình của bạn được liên kết tĩnh, và tách ra một chương trình chức năng duy nhất để chỉ cần gọi GetHostByName(). Cho phép sau này được liên kết động. Sử dụng fork sau đó exec thực hiện chương trình riêng biệt này để lấy địa chỉ cho một tên miền. Thay vì fork thì exec bạn có thể sử dụng system() mặc dù phải mất nhiều thời gian hơn (toàn bộ mili giây) không đáng lo ngại vì bạn đang tìm kiếm máy chủ tên trên internet, điều này mất một thời gian.

  2. Viết mã nguồn để thực hiện DNS, như tôi đã làm. Biên dịch nó thành một kho lưu trữ (.a) và tìm kiếm nó trong liên kết tĩnh.

5

Tôi nhận được cùng một cảnh báo và khắc phục nó tôi đã biên dịch lại glibc. Bật công tắc --enable-static-nss khi định cấu hình để thiết bị hoạt động.

Các vấn đề liên quan