如果我得到一个初始的“名称或服务未知”(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
  • 如果同时满足以上两个条件,它将尝试仅查询nscd。
  • 同样,在尝试查询nscd时,该计数也会立即重置为零。
    从而在下次调用NSS_NSCD_RETRY时忽略nscd。
  • 此外,nscd在以下地方还对 getaddrinfo() 进行了内部修改
  • __nss_not_use_nscd_hosts 第178、189行
    -重置为1
  • nscd/nscd_gethst_r.c第89、164行
    -重置为1
  • nscd/nscd_getai.c
    -设置为-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/

    10-11 08:09