Linux 是怎样使用内存的?


阿凡达提问于 2018-08-14 12:43
1 个回答
  • 前言: 内存是linux中很重要的一块,内存不足、内存泄漏、内存溢出也是在测试项目中经常会遇到的问题。


    1. 物理内存和虚拟内存

    内存的读写性能要比硬盘快的多,因此,在设计上会充分利用内存进行数据的读取和写入,提高性能,但是内存是有限的,这就引入了物理内存和虚拟内存的概念。

    物理内存指通过物理内存条而获得的内存空间,称为RAM。而虚拟内存则是指将硬盘的一块区域划分来作为内存。内存主要作用是在计算机运行时为操作系统和各种程序提供临时储存。当物理内存不足时,可以用虚拟内存代替。虚拟内存的概念,是为了满足物理内存不足的情况下,利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(swap space)。vm.swappiness是Linux内核的一个参数,范围是0~100。它表示实际内存和虚拟内存区域进行数据交换的倾向性大小,数值越大表示倾向性越大,即交换的页面文件越多,反之亦然。一般默认值为60。可用'cat /proc/sys/vm/swappiness’查看。


    Linux会在物理内存不足的时,使用交换分区的虚拟内存,也就是说,内核会将暂时不用的内存块信息写到交换空间,以释放物理内存。Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。swap si/so 交换区的换进换出。


    所有的进程都需要内存,但是不是每个进程都需要一直将对象加载到内存中。基于这点,kernel通过将进程的部分或全部内存换出到磁盘上,来释放物理内存,直到需要再次使用,然后再次读到内存中。kernel采用分页和交换进行内存管理。其中:

    si:将分页被重新读取到物理内存。也称作page-in

    so:将内存的要交换的分页写到磁盘上。也称作page-out


    2. Buffer与Cache

    buffer 和 cache都是通过使用物理内存的一部分,其中A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use.


    但是我们平常对系统资源进行监控时看到的buffer cache,其实都是cache,其中,buffer是buffer cache,cache是page cache,例如free命令中展示的结果:

    <figure>

    Mem是物理内存统计,如上面显示的,total表示物理内存总量是8006M,used表示总计分配给缓存(包括buffers和cached的)使用的数量,但其中可能部分缓存并未实际使用。used使用的内存有7253M,free未被分配的内存为752M,共享内存shared 一般系统不会用到,总是0。Buffer是系统分配但未被使用的buffer数量有183M,cache是系统分配但未被使用的cache数量有5153M,关系:total(8006M) = used(7253M) + free(752M),除去buffer和cache,真正使用的内存即-/+ buffers/cache中显示的used的值,也就是1934M。即下面的关系:

    (-buffers/cache) used内存数:1934M (指的第一部Mem行中的used–buffers– cached) (+buffers/cache) free内存数: 6071M (指的第一部分Mem行中的free + buffers + cached) 所以-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数。

    3. Linux下的内存的监控方法


    1)free命令查看内存

    在linux下用free –help查看使用规则,详见1.2节

    参数:

    -b  以Byte为单位显示内存使用情况。

    -k  以KB为单位显示内存使用情况。

    -m  以MB为单位显示内存使用情况。

    -o  不显示缓冲区调节列。

    -s<间隔秒数>  持续观察内存使用状况。

    -t  显示内存总和列。

    -V  显示版本信息。

    2) vmstat命令查看内存

    vmstat 1 【Virtual Meomory Statistics(虚拟内存统计)】命令查看内存使用情况:


    其中

    Procs(进程):

    r: 运行队列中进程数量(runnable),当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系;

    b: 表示阻塞的进程,等待IO的进程数量(blocked)

    Memory(内存):

    swpd: 使用虚拟内存大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。;

    free: 空闲的物理内存大小;

    buff: 用作缓冲的内存大小,Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存;

    cache: 用作缓存的内存大小,直接用来记忆我们打开的文件,给文件做缓冲;

    Swap:

    si: 每秒从磁盘写到内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉;

    so: 每秒写入磁盘的内存大小;

    【内存够用的时候,这两个值都为0,若这两个值长期大于0时,系统性能会受到影响,并且磁盘IO 和cpu资源都会被消耗】

    bi: 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0;

    bo: 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0;

    【bi和bo一般都要接近0,不然就是IO过于频繁,需要调整】

    system:

    in: 每秒cpu中断数,包括时间中断。

    cs: 每秒上下文切换数。(content switch)

    这两个值越大,说明cpu里面的sys会越大

    CPU(以百分比表示):

    us: 用户进程执行时间(user time);

    sy: 系统进程执行时间(system time);

    id: 空闲时间(包括IO等待时间),中央处理器的空闲时间【越接近0表示cpu越繁忙】 。以百分比表示;

    wa: 进程等待IO完成而使cpu处于空闲状态的时间片比例

    这个命令中应该主要看参数: r,b,si,so


    3) sar命令

    sar –R和sar –r可以用来监控内存问题


    kbmemfree:这个值和free命令中的free值基本一致,所以它不包括buffer和cache的空间.

    kbmemused:这个值和free命令中的used值基本一致,所以它包括buffer和cache的空间.

    %memused:这个值是kbmemused和内存总量(不包括swap)的一个百分比.

    kbbuffers和kbcached:这两个值就是free命令中的buffer和cache.

    kbcommit:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap).

    %commit:这个值是kbcommit与内存总量(包括swap)的一个百分比。


    4. 内存泄漏和内存溢出

    内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

    内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄漏可以从如下方法中进行判断:

    1)jvisualvm中查看堆的变化,如下左图是正常的,右图就是发生了内存泄漏的:


    2)用 jstat -gcutil PID,观察Old这个参数,如果每次执行完FULLGC之后Old区的值一次比一次升高,就可以判断为发生了内存泄漏。


    以上答案来自我厂齐红方老师的博文《linux内存浅析》。