这是新公司有个同事提到的,我刚好是负责这一块的,于是给他解答如下。

 

问题:

写了一个简单的测试程序,申请2G内存但不使用,理论上不使用的内存不会占用系统的物理内存和swap。top显示这个进程使用了2G swap,但整个系统只使用了1G swap。感觉TOP显示的swap信息完全是忽悠。

top - 12:03:30 up 109 days,  4:14, 16 users,  load average: 1.00, 1.02, 1.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  9.2%us,  3.4%sy,  0.0%ni, 87.5%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  12462160k total,  7966312k used,  4495848k free,   465772k buffers
Swap :  4192956k total,  1257252k used ,  2935704k free,  5561148k cached

  PID USER      PR  VIRT  RES  SHR S %CPU %MEM    TIME+  SWAP DATA COMMAND                                                              
22051 zhouzm    15 2050m  388  320 S  0.0  0.0   0:00.00 2.0g 2.0g a.out

 




 

解答:

汇总区域显示的Swap: 1257252k used是正确的,不过任务区域的SWAP 2.0g其实也不算是错的,我觉得是表达的意义不一样。top源代码里面,不像其它参数,SWAP不是直接读取/proc/pid/stat文件数据的, 是这样计算的:SWAP = VIRT - RES,依赖于VIRT和RES。其中,VIRT(虚拟内存)是分配和释放内存时会变化的,而RES(即RAM)是使用的时候随着页面交换变化的。在刚分配大量内存但还没有使用的时候,VIRT明显变大但RES没有明显变化,导致SWAP变得出奇的大。

以下是我分配和使用2G大的数组,使用top捕捉到的变化过程:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  SWAP COMMAND

before malloc 2G memory
4415 liangry   16   0  2404  248  192 S  0.0  0.0   0:00.00 2156 test_top_swap

after malloc 2G memory
4415 liangry   16   0 2050m  292  228 S  0.0  0.0   0:00.00 2.0g test_top_swap

start using the array
4415 liangry   25   0 2050m 733m  260 R 99.9 73.3   0:03.57 1.3g test_top_swap

end of assignment
4415 liangry   18   0 2050m 893m   84 R 24.3 89.3   0:11.19 1.1g test_top_swap

 

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
    sleep(15);
    long size = (long) 1024 * 1024 * 1024 * 2;
    char *s = (char *) malloc(sizeof(char) * size);
    sleep(15);
    long offset = 0;
    printf("starting.../n");
    while ( offset < size ) {
        strcpy(s + offset, "hello");
        offset += strlen("hello");
    }
    printf("sleeping.../n");
    sleep(99999);
    free(s);
    return 0;
}