NPTL引起linux系统无法分配内存


linux系统出现

-bash: fork: Cannot allocate memory

查看系统内存

可用内存充足, 交互分区没被使用,

-bash: fork: Cannot allocate memory
-bash: fork: Cannot allocate memory
-bash: fork: Cannot allocate memory
[root@node1 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:            31G         18G        956M        133M         11G         11G
Swap:           15G         78M         15G

查看系统内存分配策略

overcommit_memory

-bash: fork: Cannot allocate memory
-bash: fork: Cannot allocate memory
[root@node1 ~]# cat /proc/sys/vm/overcommit_memory
1
-bash: fork: Cannot allocate memory
-bash: fork: Cannot allocate memory

内存分配策略
* 0,系统在为应用进程分配虚拟地址空间时,会判断当前申请的虚拟地址空间大小是否超过剩余内存大小,如果超过,则虚拟地址空间分配失败。因此,也就是如果进程本身占用的虚拟地址空间比较大或者剩余内存比较小时,fork、malloc等调用可能会失败。

  • 1,系统在为应用进程分配虚拟地址空间时,完全不进行限制,这种情况下,避免了fork可能产生的失败,但由于malloc是先分配虚拟地址空间,而后通过异常陷入内核分配真正的物理内存,在内存不足的情况下,这相当于完全屏蔽了应用进程对系统内存状态的感知,即malloc总是能成功,一旦内存不足,会引起系统OOM杀进程,应用程序对于这种后果是无法预测的
  • 2,则是根据系统内存状态确定了虚拟地址空间的上限,由于很多情况下,进程的虚拟地址空间占用远大小其实际占用的物理内存,这样一旦内存使用量上去以后,对于一些动态产生的进程(需要复制父进程地址空间)则很容易创建失败,如果业务过程没有过多的这种动态申请内存或者创建子进程,则影响不大,否则会产生比较大的影响

什么是Overcommit和OOM

  • Linux对大部分申请内存的请求都回复”yes”,以便能跑更多更大的程序。因为申请内存后,并不会马上使用内存。这种技术叫做Overcommit。当linux发现内存不足时,会发生OOM killer(OOM=out-of-memory)。它会选择杀死一些进程(用户态进程,不是内核线程),以便释放内存。
  • 当oom-killer发生时,linux会选择杀死哪些进程?选择进程的函数是oom_badness函数(在mm/oom_kill.c中),该函数会计算每个进程的点数(0~1000)。点数越高,这个进程越有可能被杀死。每个进程的点数跟oom_score_adj有关,而且oom_score_adj可以被设置(-1000最低,1000最高)。

进程情况

[root@node1 ~]# ps -ef |wc -l
348

[root@node1 ~]# cat  /proc/sys/kernel/pid_max
32768

实际上,最终发现我们的应用程序由于资源泄漏,jvm已经开启了3W多个线程.

NPTL

Native POSIX Thread Library(NPTL)是Linux内核中实践POSIX Threads标准的库。

NPTL的解决方法与LinuxThreads类似,内核看到的首要抽象依然是一个进程,新线程是通过clone()系统调用产生的。但是NPTL需要特殊的内核支持来解决同步的原始类型之间互相竞争的状况。在这种情况下线程必须能够入眠和再复苏。用来完成这个任务的原始类型叫做futex。


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: