写点什么

Linux 下内存不足问题的定位与处理

用户头像
明儿
关注
发布于: 2021 年 05 月 10 日
Linux下内存不足问题的定位与处理

今天分享实际工作中,在 Linux 下内存不足问题以及解决思路,希望可以帮助定位并且处理,系统性能问题。


内存不足的判断


做后台开发,常常会往某个设备回放报文冲流量,有时会遇到一些因为内存不足而导致编译失败的情况。最典型的是,使用 gcc/g++编译出现 internal compiler error:Killed,就是一个典型的因为内存(Memory)不足的错误。我们也可以提前用 free 命令查看。


下面通过如下方法判断是否存在内存不存:


执行命令 free,查看 -/+ buff 开头一行的 free 列即为当前空闲内存


total used free shared buffers cached Mem: 885600 818848 66752 0 21272 648200 -/+ buffers/cache: 149376 736224 Swap: 2064376 1352 206304


使用 top 命令查看内存大小



注意:top 命令里有 free 字段,该字段并不是指当前的有效空闲内存大小。


swap 行的 used 如不为 0,则表示系统使用了交换内存,这会导致换页操作,会导致 io 过高,这时很容易产生丢包。


如果系统瓶颈为 cpu 运算,内存足够则需要避免使用交换内存,调整该功能的方法如下:


echo “100” > /proc/sys/vm/swappiness
复制代码



swappiness 表示使用了多少内存才开始使用 swap 交换功能。也可以把设置写在 /etc/sysctl.conf 中,即在该文件中追加一行:


vm.swappiness = 100
复制代码


这样每次重启就会自动设置该值。


内存使用的分配


解决内存问题,实现需要知道哪些地方消耗了内存。内存消耗有如下个地方:应用程序,内核,内存文件系统,大页内存


下面通过查看/proc/meminfo 了解系统内存使用:



需要关注的是如下几点:


AnonPages : 用户进程使用的内存,因为内存分配均采用匿名映射的方式 mmap。


Mapped :文件映射使用的内存,即 mmap。


SUnreclaimable :即不可回收的 slap,这是内核消耗的内存。


HugePages_Total :主动分配的大页内存。这个值如果过大,查看


/sys/kernel/mm/hugepages/hugepages-xxkB/nr_hugepages
复制代码


xx 为 1024,2048,4096 等,看这些文件有没有值,有则进一步查看是哪里设置的,为什么这样设置。



Shmem :共享内存,内存文件系统也是基于共享内存机制,这个值大,提示需查看内存文件系统:


mount |grep ’ tmpfs '|awk ‘{print $3}’
复制代码


看看对应目录是不是有内容。


查看用户进程使用的内存


知道内存由用户进程引起后,需查出是哪个进程导致的,执行 top


查看 RES 项即为进程当前分配的内存大小。


VIRT 指虚拟内存大小,即可能会用这么多内存,但是没给进给进程分配那么多内存。内存是按进程分的,所有看内存时不必查看个线程的内存使用。


valgrind 定位内存泄露


如果使用 top 定期查看进程 RES 内存一致增大,不能稳在一个值上,就可能有内存泄露,可以使用 valgrind 辅助诊断。


valgrind --tool=memcheck --leak-check=full ./t



运行一段时间按 CTLL+C 退出,如上图:definitely lost :表示检测出确定泄露的内存,也可以看出问题的行数。


有时 definitely lost 没问题,possibly lost 有问题,或 indirectly lost 有问题,也要注意,需要看相应的代码才能判断是否有问题。


有时在运行中,屏幕会不断有告警打印,这种情况也要注意,要分析打印的意思。


注意:valgrind 工具本身会极大拖慢程序的执行,很多情景下不能使用,或者结果不可信。


内存不足导致进程被 kill 问题的处理


有时进程莫名奇妙重启,没有段错误,需要怀疑是否发生了 out of memory 问题,导致 kill 掉进程,判断方法很简单,查看系统日志,可以使用 dmesg 命令查看。


内核耗内存过多的定位处理


内核消耗内存过多现象比较好确定,就是看/proc/meminfo 的 SUnreclaimable,要查具体原因并不容易,原因一般为内核机制如消息队列消耗(这个还是由用户程序间接引起),新加的内核模块编写不好(通过卸载该模块是不会把内存降下来的)



建议的方法如下:


查看那类 slab 消耗了内存,slab 是内核内存分配的单元,不同的代码会使用不同名字的 slab 分配内存,使用下面命令检测 slap 的变化。


slabtop 命令:



如果某个 slap 会不断增大,问题会容易解决,此时只需用不断查看内核调用栈,总能提取到不断分配内存的调用栈,根据函数名就可以知道是什么地方导致问题。


dmesg -c;echo “t" > /proc/sysrq-trigger ;dmesg > d.log
复制代码


消息队列使用不当,即写数据超过读数据,是导致内存耗尽的一个常见原因,此时,slabtop 会显示,szie-4096 的 slab 不断 增多,内核 调用栈也会提示是 sys_sndmsg 函数导致的 kmem_cache_alloc 的执行。 怀疑消息队列有问题,执行命令查看详情:


cat /proc/sysvipc/msg


在这里插入图片描述上面的信息中,cbytes 表示队列占用的内存,lspid 发送者 pid, lrpid 接收者 pid, 最后 2 项就可以找出问题的进程。


总结


今天主要写一写笔记,记录一下在实践中内存不足问题,以及处理。最后,合理规划和设计 Linux 内存的使用,是非常重要的!

发布于: 2021 年 05 月 10 日阅读数: 20
用户头像

明儿

关注

专注分享Linux c/c++ 、Python、Go语言。 2021.04.19 加入

彩虹风雨后,成功细节中。

评论

发布
暂无评论
Linux下内存不足问题的定位与处理