Linux 编译一个静态二进制文件,其中有一个函数 gethostbyname
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15165306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compile a static binary which code there a function gethostbyname
提问by Loren Ramly
How to resolve compile a static binary which code include a function gethostbyname and if compiled without warning like this:
如何解决编译静态二进制文件,其中代码包含函数 gethostbyname 并且如果在没有警告的情况下编译如下:
warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
警告:在静态链接的应用程序中使用“gethostbyname”需要在运行时使用 glibc 版本中用于链接的共享库
I compile on ubuntu 12.04 with command:
我使用命令在 ubuntu 12.04 上编译:
$ gcc -static lookup.c -o lookup
This is code for lookup.c:
这是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;
}
I want to if I check via $ file lookup
will get output like this:
我想如果我检查通过$ file lookup
会得到这样的输出:
lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=0x6fcb2684ad8e5e842036936abb50911cdde47c73, not stripped
查找:ELF 32 位 LSB 可执行文件,Intel 80386,版本 1 (GNU/Linux),静态链接,用于 GNU/Linux 2.6.24,BuildID[sha1]=0x6fcb2684ad8e5e842036936abb50911cdde47c73,未剥离
Not like this:
不是这样的:
lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xf9f18671751927bea80de676d207664abfdcf5dc, not stripped
查找:ELF 32 位 LSB 可执行文件,Intel 80386,版本 1 (SYSV),动态链接(使用共享库),用于 GNU/Linux 2.6.24,BuildID[sha1]=0xf9f18671751927bea80de676d207664abfdcf5dc
If you commented with suggested I must use without static because different libc every linux I knew it, I hope you do not need to comment. Why do I persist in for static? Because there I need to do to mandatory use static, binary files must be static and not dynamic.
如果你评论了建议我必须不使用静态,因为我知道的每个 linux 都有不同的 libc,我希望你不需要评论。为什么我坚持静态?因为那里我需要强制使用静态,二进制文件必须是静态的而不是动态的。
I have more than 2 weeks looking for this but so far have not succeeded.
我有超过 2 周的时间来寻找这个,但到目前为止还没有成功。
Thanks for help me to resolve my heavy problem.
感谢您帮助我解决我的沉重问题。
采纳答案by Borealid
What you are asking for is going to be very difficult.
你所要求的将是非常困难的。
See this StackOverflow question about getaddrinfo. Basically, underneath getaddrinfo
/gethostbyname
is glibc's NSS layer. This allows a sysadmin to say "use DNS for resolving hostnames to IP addresses", or "use LDAP", or "don't use anything other than /etc/hosts
". This control is at runtime; the sysadmin can at any point change the way hostnames are resolved to IPs.
请参阅有关 getaddrinfo 的此 StackOverflow 问题。基本上,在getaddrinfo
/下面gethostbyname
是 glibc 的 NSS 层。这允许系统管理员说“使用 DNS 将主机名解析为 IP 地址”,或“使用 LDAP”,或“不要使用除/etc/hosts
”以外的任何内容。此控件在运行时;系统管理员可以随时更改主机名解析为 IP 的方式。
Because of this flexibility, all of the name-resolution calls in glibc use helper libraries (plugins, basically) to do the grunt work of resolution. There's one shared library for LDAP addressing, one for files, one for DNS, one for YP, and so on and so on.
由于这种灵活性,glibc 中的所有名称解析调用都使用帮助程序库(基本上是插件)来完成解析的繁重工作。有一个用于 LDAP 寻址的共享库,一个用于文件,一个用于 DNS,一个用于 YP,等等。
If you want your program to be 100% statically linked, you're going to have to go elsewhere (NOT gethostbyname
) to convert a hostname to an IP address. You could do this with a resolver library like uDNS(not this exact one - there are similar tools available), but you should keep in mind that your binary is not going to do the right thing on systems which are configured not to use DNS!
如果您希望您的程序 100% 静态链接,您将不得不去其他地方 (NOT gethostbyname
) 将主机名转换为 IP 地址。您可以使用像uDNS这样的解析器库(不是这个确切的 - 有类似的工具可用)来做到这一点,但您应该记住,您的二进制文件不会在配置为不使用 DNS 的系统上做正确的事情!
Instead, I would recommend just leaving the program (technically) dynamically linked. If you really want to make sure it will run on any platform, you could even ship glibc
with the binary - although doing this would require LGPL conformance. Leaving this one dynamic link in place will only mean you won't work on systems with the wrong glibc
version - not a huge compatibility issue.
相反,我建议只让程序(技术上)动态链接。如果您真的想确保它可以在任何平台上运行,您甚至可以glibc
附带二进制文件 - 尽管这样做需要符合 LGPL。保留这个动态链接只会意味着您不会在glibc
版本错误的系统上工作- 不是一个巨大的兼容性问题。
Speaking of license compliance, it's worth noting that if you statically link glibc
, you most likely have to ship the source code for your entire applicationto comply with glibc
's LGPL license. I am not a lawyer, and this is not qualified legal advice, but reading the LGPL makes it very clear that applications statically linking glibc
must be open-source. See this StackOverflow question on the topic.
说到许可证合规性,值得注意的是,如果您静态链接glibc
,则很可能必须提供整个应用程序的源代码以符合glibc
的 LGPL 许可证。我不是律师,这不是合格的法律建议,但阅读 LGPL 可以清楚地表明静态链接的应用程序glibc
必须是开源的。请参阅有关该主题的 StackOverflow 问题。
回答by Clive
I have 2 answers -
我有2个答案-
Keep the main part of your program statically linked, and separate out a single function program to just call gethostbyname(). Allow the latter to be dynamically linked. Using fork then exec execute this separate program to get the address for a domain name. Instead of fork then exec you could use system() though it takes longer (a whole millisecond) that should not be of concern since you're searching nameservers on the internet anyway, which takes a time.
Write the source code to do the DNS, as I have done. Compile it into an archive (.a) and have it searched in the static linking.
保持程序的主要部分静态链接,并分离出一个函数程序来调用 gethostbyname()。允许后者动态链接。使用 fork 然后 exec 执行这个单独的程序来获取域名的地址。您可以使用 system() 而不是 fork then exec 虽然它需要更长的时间(整整毫秒),但您不必担心,因为无论如何您都在互联网上搜索名称服务器,这需要时间。
像我一样,编写源代码来做 DNS。将其编译为存档 (.a) 并在静态链接中进行搜索。
回答by kimi shi
I get the same warning and to fix it I recompiled glibc. Turn on switch --enable-static-nss
when configuring to get it to work.
我收到相同的警告并修复它,我重新编译了 glibc。--enable-static-nss
配置时打开开关以使其工作。