下面主要从以下方面介绍linux内存管理:进程的内存申请与分配内存耗尽之后OOM申请的内存都在哪?系统回收内存进程的内存申请与分配之前有篇文章介绍helloworld程序是如何载入内存以及是如何申请内存的;我在这,再次说明下;同样,还是先给出进程的地址空间,我觉得对于任何开发人员这张图是必须记住的,还有一张就是操作disk,memory以及cpucache的时间图;当我们在终端启动一个程序时,终端进程调用exec函数将可执行文件载入内存,此时代码段,数据段,bbs段,stack段都通过mmap函数映射到内存空间,堆则要根据是否有在堆上申请内存来决定是否映射;exec执行之后,此时并未真正开始执行进程,而是将cpu控制权交给了动态链接库装载器,由它来将该进程需要的动态链接库装载进内存;之后才开始进程的执行;这个过程可以通过strace命令跟踪进程调用的系统函数来分析,这是我上篇博客认识pipe中的程序,从这个输出过程,可以看出和我上述描述的一致;当第一次调用malloc申请内存时,通过系统调用brk嵌入到内核,首先会进行一次判断,是否有关于堆的vma,如果没有,则通过mmap匿名映射一块内存给堆,并建立vma结构,挂到mm_struct描述符上的红黑树和链表上;然后回到用户态,通过内存分配器(ptmaloc,tcmalloc,jemalloc)算法将分配到的内存进行管理,返回给用户所需要的内存;如果用户态申请大内存时,是直接调用mmap分配内存,此时返回给用户态的内存还是虚拟内存,直到第一次访问返回的内存时,才真正进行内存的分配;其实通过brk返回的也是虚拟内存,但是经过内存分配器进行切割分配之后(切割就必须访问内存),全都分配到了物理内存当进程在用户态通过调用free释放内存时,如果这块内存是通过mmap分配,则调用munmap直接返回给系统;否则内存是先返回给内存分配器,然后由内存分配器统一返还给系统,这就是为什么当我们调用free回收内存之后,再次访问这块内存时,可能不会报错的原因;当然,当整个进程退出之后,这个进程占用的内存都会归还给系统;内存耗尽之后OOM在实习期间,有一台测试机上的mysql实例经常被oom杀死;oom(outofmemory)即为系统在内存耗尽时的自我拯救措施,他会选择一个进程,将其杀死,释放出内存;很明显,哪个进程占用的内存最多,即最可能被杀死,但事实是这样的吗?今天早上去上班,刚好碰到了一起OOM,突然发现,oom一次,世界都安静下来了,哈哈;测试机上的redis被杀死了;OOM关键文件oom_kill.c,里面介绍了当内存不够时,系统如何选择最应该被杀死的进程;选择因素有挺多的,除了进程占用的内存外,还有进程运行的时间,进程的优先级,是否为root用户进程,子进程个数和占用内存以及用户控制参数oom_adj都相关;当产生oom之后,函数select_bad_process会遍历所有进程,通过之前提到的那些因素,每个进程都会得到一个oom_score分数,分数最高,则被选为杀死的进程;我们可以通过设置/proc/pid/oom_adj分数来干预系统选择杀死的进程;这是内核关于这个oom_adj调整值的定义;最大可以调整为15,最小为-16,如果为-17,则该进程就像买了vip会员一样,不会被系统驱逐杀死了;因此,如果在一台机器上有跑很多服务器,且你不希望自己的服务被杀死的话,就可以设置自己服务的oom_adj为-17;当然,说到这,就必须提到另一个参数/proc/sys/vm/over
转载请注明:http://www.aierlanlan.com/rzdk/8724.html