col*_*.mc 11 c linux nss getaddrinfo
如果我得到一个初始的"名称或服务未知"(EAI_NONAME),下一次调用getaddrinfo()似乎直接转到dns而不是先检查缓存(nscd日志显示没有查找尝试,tcpdump显示流量到DNS服务器).如果第一次调用成功获取地址,从那时起,所有getaddrinfo()调用首先转到nscd,如预期的那样.
我正在针对arm linux编译glibc-2.13.在我的rc.d中,nscd在我的守护进程之前启动.nscd设置为禁止共享缓存,并维护主机缓存.我正在使用busybox中的nscd(0.47).设置了nsswitch.conf,以便主机检查cache/files/dns.hosts.conf设置为check files/bind.
我的守护进程正在调用getaddrinfo().
我有运行nscd的调试日志,它们显示客户端开始读取DNS响应关闭时出现"Broken Pipe"错误.
之后它会显示其他守护进程试图使用缓存的GAI尝试(所以我知道它不是nscd锁定或任何东西),但是获得EAI_NONAME的守护进程再也不会联系nscd进行缓存查找.
如果我重新启动守护程序,如果第一个DNS查询再次超时,我会得到相同的行为.
glibc中有什么东西使我的守护进程到缓存的链接无效吗?有没有办法将我的守护进程重新连接到缓存而不重新启动它(类似于通过res_init()强制resolv.conf重新加载)?
正如他在评论中提到的那样,重试getaddrinfo()超过100次应强制进行nscd查询.
要理解为什么,让我们快速浏览一下到执行的流程内 的getaddrinfo() .
gaih_inet()
执行以下操作__nss_not_use_nscd_hosts:
检查它是否超过重试次数NSS_NSCD_RETRY?
如果满足上述两个条件,它仅尝试查询nscd.
另外在尝试查询到NSCD,计数立即重置为零
,从而忽略nscd的下一个NSS_NSCD_RETRY时间getaddrinfo()被调用.
__nss_not_use_nscd_hosts在以下位置也由nscd在内部修改
nscd/nscd_gethst_r.c第178,189行
- 重置为1.
nscd/nscd_getai.c第89,164行
- 重置为1.
nss/nsswitch.c,第709行
 
- 设置为-1ie禁用nscd.
基于以上所述,可以得出结论,
getaddrinfo()每次都不查询nscd.
nscd的内部状态(由...确定__nss_not_use_nscd_hosts)
决定是否getaddrinfo()最终调用nscd.
为了真正强制绕过100重试限制,可以修改
NSS_NSCD_RETRY和重建libc以偏离标准行为.但我不确定这是否会导致任何其他无意识的回归.
参考:介绍逻辑的补丁.__nss_not_use_nscd_hostsgetaddrinfo()