问题简要描述:Intel Core-2 Q6600 上的 64 位 Gentoo 报告重启后 8GB 总内存中大约使用了 3GB。该内存既不被任何进程占用,也不被缓冲区/缓存使用。
语境:emerge
在尝试从源代码构建八度音阶时,OOM 终止了进程后,我第一次注意到这种行为。当系统再次响应时,仍然有大约 3GB 的已用内存未被任何进程使用。 (请注意,我不能肯定地说这真的是在一开始——也许我只是之前没有注意到。)
我尝试重新启动,因为我不熟悉 OOM 可能出现的问题,但据报道内存又被使用了。
然后我尝试了 Memcheck86+,它在 3246.3MB 上报告了一个“失败地址”错误(测试重复了 5 次)。我降低了 RAM 频率,错误消失了(测试重复 3 次)。
然而,在我的 Gentoo 上,持续报告已使用 3GB,但没有明显的解释(请参阅下面的诊断报告)。
我还尝试过一个实时发行版(Parted Magic),它显然表现正常(启动后大约使用了数百个内存)。
关于可能的原因甚至解决方案有什么建议吗?
编辑: 我现在能够克服这个问题,但仍然无法解释它。我描述一下我到目前为止所追踪的内容:
- 以单用户模式启动时不使用 3GB 内存。
启动
iptables
结果为 3GB 使用量,而 dmesg 报告:nf_conntrack:回退到 vmalloc
随后的停止
iptables
不会恢复进程,内存仍然被使用。
然后我更改了内核配置,使其nf_conntrack
不再是内置的,而是作为模块加载。重新启动后,iptables
启动时不会出现任何falling back to vmalloc
消息,也不消耗 3GB。
我不知道该如何解释。也许一些内核开发人员可以帮忙解释一下,到底是什么导致了这种行为?
相关报道:
答案1
此问题可能是由于连接跟踪表和哈希表的最大大小设置不正确造成的。 Linux 内核尝试分配连续的页面来跟踪 iptables nf_conntrack 模块的连接表。由于没有足够的物理内存,conntrack 会失败返回到 vmalloc。
该表不是根据已建立的连接动态创建的,而是根据某些内核参数完全分配的。
一些额外的症状可能是发现大量nf_conntrack:回退到 vmalloc。/var/log/messages(或 /var/log/kern.log,或两者)中的消息。
只需微调连接轨道表并缩小其大小即可轻松解决此问题。必须根据系统使用情况进行适当的调整。如果您在此系统中运行专用网络防火墙,则连接跟踪表需要很高,但如果您只是使用 iptables 来保护其免受网络入侵,则连接跟踪表可以低得多。
有关连接跟踪调整的更多信息,请参阅https://wiki.khnet.info/index.php/Conntrack_tuning
conntrack -L
要微调系统的值,您可以首先通过运行(或 )来评估系统保持打开的连接数 /sbin/sysctl net.netfilter.nf_conntrack_count
。更好的是,保留一段时间内跟踪连接的统计数据(穆宁做得很好)并使用最大跟踪连接数作为基线。根据此信息,您可以相应地配置 /etc/sysctl.conf。
进行微调时,请确保您还检查在跟踪表中保留连接的时间。有时,由于网络配置错误或错误,conntrack 表包含虚假数据连接。例如,当服务器收到从未关闭的 SYN 连接时,或者当客户端突然断开连接并长时间保持打开的套接字时。
其次,检查您的 conntrack 条目是否有意义。有时,由于某些网络或防火墙配置错误,conntrack 表中充满了垃圾。通常这些是从未完全建立的连接条目。例如,当服务器收到传入连接 SYN 数据包时,可能会发生这种情况,但服务器回复总是在网络上的某个地方丢失。
当微调这些值时,运行sysctl -a | grep conntrack | grep timeout
可能会提供一些见解。默认值相当保守:一般超时为 600(10 分钟),已建立的 TCP 连接为 432000(5 天)。根据系统用途和网络行为,可能需要对这些进行微调以减少 conntrack 表中的活动连接数量。这将有助于为其定义较低的值。
但是,请确保不要将 conntrack 表的大小缩小太多,否则可能会产生相反的效果:连接被 iptables 删除,因为它们无法被跟踪,并且您的日志文件中将开始出现如下消息:“内核:ip_conntrack:表已满,正在丢弃数据包。”
为了确认这是否是问题所在,请提供以下输出:
cat /proc/sys/net/ipv4/ip_conntrack_max
cat /proc/sys/net/ipv4/netfilter/ip_conntrack_buckets