如果我得到一个初始的“名称或服务未知”(EAI_NONAME),则对getaddrinfo()的下一次调用似乎直接进入了dns,而不是首先检查了缓存(nscd日志显示没有查找尝试,tcpdump显示到DNS服务器的流量)。如果第一个调用成功获取地址,则从此开始,所有getaddrinfo()调用都将首先到达nscd,这与预期的一样。
我正在针对arm linux针对glibc-2.13进行编译。在我的rc.d中,nscd在守护程序之前启动。 nscd设置为禁止共享缓存,并维护主机缓存。我正在使用busybox(0.47)中的nscd。设置nsswitch.conf以便主机检查缓存/文件/dns。 hosts.conf设置为检查文件/绑定(bind)。
我的守护进程正在调用getaddrinfo()。
我有运行nscd的调试日志,它们显示客户端开始读取DNS响应时关闭,并显示“Broken Pipe”错误。
之后,它将显示来自其他尝试使用缓存的守护程序的GAI尝试(因此我知道它没有被nscd锁定或其他任何东西),但是获得EAI_NONAME的守护程序再也不会联系nscd来进行缓存查找。
如果重新启动守护程序,如果第一个DNS查询再次超时,我将获得相同的行为。
glibc中是否有某些东西会使我的守护程序到缓存的链接无效?有没有一种方法可以将守护进程重新连接到缓存而无需重新启动它(类似于通过res_init()强制resolv.conf重新加载)?
最佳答案
作为alk mentions in his comment,重试getaddrinfo()
超过100次应强制执行nscd查询。
为了理解原因,让我们快速浏览 getaddrinfo()内部的执行流程。
getaddrinfo()
calls gaih_inet。 gaih_inet()
对
__nss_not_use_nscd_hosts
执行以下操作:NSS_NSCD_RETRY
?从而在下次调用
NSS_NSCD_RETRY
时忽略nscd。 getaddrinfo()
进行了内部修改__nss_not_use_nscd_hosts
第178、189行-重置为
1
。 -重置为
1
。 -设置为
-1
,即禁用nscd。 nscd的内部状态(由
__nss_not_use_nscd_hosts
确定)决定
getaddrinfo()
是否最终调用nscd。引用:nss/nsswitch.c, line 709在
__nss_not_use_nscd_hosts
中介绍了getaddrinfo()
逻辑。关于c - 使用getaddrinfo()仅在DNS超时的情况下才第一次检查nscd缓存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16741732/