设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Linux内存点滴:用户进程内存空间

2013-8-30 11:40| 发布者: 红黑魂| 查看: 10255| 评论: 1|来自: 伯乐在线

摘要: 原文出处:PerfGeeks经常使用top命令了解进程信息,其中包括内存方面的信息。命令top帮助文档是这么解释各个字段的。VIRT , Virtual Image (kb)RES, Resident size (kb)SHR, Shared Mem size (kb)%MEM, Memory usage ...
原文出处: PerfGeeks


经常使用top命令了解进程信息,其中包括内存方面的信息。命令top帮助文档是这么解释各个字段的。
VIRT , Virtual Image (kb)
RES, Resident size (kb)
SHR, Shared Mem size (kb)
%MEM, Memory usage(kb)
SWAP, Swapped size (kb)
CODE, Code size (kb)
DATA, Data+Stack size (kb)
nFLT, Page Fault count
nDRT, Dirty Pages count
尽管有注释,但依然感觉有些晦涩,不知所指何意?

进程内存空间

正在运行的程序,叫进程。每个进程都有完全属于自己的,独立的,不被干扰的内存空间。此空间,被分成几个段(Segment),分别是Text, Data, BSS, Heap, Stack。用户进程内存空间,也是系统内核分配给该进程的VM(虚拟内存),但并不表示这个进程占用了这么多的RAM(物理内存)。这个空间有多大?命令top输出的VIRT值告诉了我们各个进程内存空间的大小(进程内存空间随着程序的执行会增大或者缩小)。你还可以通过/proc//maps,或者pmap –d 了解某个进程内存空间都分布,比如:

1
2
3
4
5
6
7
8
9
10
11
#cat /proc/1449/maps
0012e000-002a4000 r-xp 00000000 08:07 3539877    /lib/i386-linux-gnu/libc-2.13.so
002a4000-002a6000 r--p 00176000 08:07 3539877    /lib/i386-linux-gnu/libc-2.13.so
002a6000-002a7000 rw-p 00178000 08:07 3539877   /lib/i386-linux-gnu/libc-2.13.so
002a7000-002aa000 rw-p 00000000 00:00 0
08048000-0875b000 r-xp 00000000 08:07 4072287    /usr/local/mysql/libexec/mysqld
0875b000-0875d000 r--p 00712000 08:07 4072287    /usr/local/mysql/libexec/mysqld
0875d000-087aa000 rw-p 00714000 08:07 4072287   /usr/local/mysql/libexec/mysqld

PS:线性地址,访问权限, offset, 设备号,inode,映射文件

VM分配与释放

“内存总是被进程占用”,这句话换过来可以这么理解:进程总是需要内存。当fork()或者exec()一个进程的时候,系统内核就会分配一定量的VM给进程,作为进程的内存空间,大小由BSS段,Data段的已定义的全局变量、静态变量、Text段中的字符直接量、程序本身的内存映像等,还有Stack段的局部变量决定。当然,还可以通过malloc()等函数动态分配内存,向上扩大heap。

动态分配与静态分配,二者最大的区别在于:1. 直到Run-Time的时候,执行动态分配,而在compile-time的时候,就已经决定好了分配多少Text+Data+BSS+Stack。2.通过malloc()动态分配的内存,需要程序员手工调用free()释放内存,否则容易导致内存泄露,而静态分配的内存则在进程执行结束后系统释放(Text, Data), 但Stack段中的数据很短暂,函数退出立即被销毁。

我们使用几个示例小程序,加深理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* @filename: example-2.c */
#include <stdio.h>
 
int main(int argc, char *argv[])
{
    char arr[] = "hello world"; /* Stack段,rw--- */
    char *p = "hello world";        /* Text段,字符串直接量, r-x--  */
    arr[1] = 'l';
    *(++p) = 'l';   /* 出错了,Text段不能write */
    return 0;
}
PS:变量p,它在Stack段,但它所指的”hello world”是一个字符串直接量,放在Text段。
 
/* @filename:example_2_2.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
char *get_str_1()
{
    char str[] = "hello world";
    return str;
}
 
char *get_str_2()
{
    char *str = "hello world";
    return str;
}
 
char *get_str_3()
{
    char tmp[] = "hello world";
    char *str;
    str = (char *)malloc(12 * sizeof(char));
    memcpy(str, tmp, 12);
    return str;
}
 
int main(int argc, char *argv[])
{
    char *str_1 = get_str_1();  //出错了,Stack段中的数据在函数退出时就销毁了
    char *str_2 = get_str_2();  //正确,指向Text段中的字符直接量,退出程序后才会回收
    char *str_3 = get_str_3();  //正确,指向Heap段中的数据,还没free()
    printf("%s\n", str_1);
    printf("%s\n", str_2);
    printf("%s\n", str_3);
    if (str_3 != NULL)
    {
        free(str_3);
        str_3 = NULL;
    }
    return 0;
}
PS:函数get_str_1()返回Stack段数据,编译时会报错。Heap中的数据,如果不用了,应该尽早释放free()。
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
char data_var  = '1';
char *mem_killer()
{
   char *p;
   p = (char *)malloc(1024*1024*4);
   memset(p, '\0', 1024*1024*4);
   p = &data_var;   //危险,内存泄露
   return p;
}
 
int main(int argc, char *argv[])
{
    char *p;
    for (;;)
    {
        p = mem_killer(); // 函数中malloc()分配的内存没办法free()
        printf("%c\n", *p);
        sleep(20);
    }
    return 0;
}

PS:使用malloc(),特别要留意heap段中的内存不用时,尽早手工free()。通过top输出的VIRT和RES两值来观察进程占用VM和RAM大小。

本节结束之前,介绍工具size。因为Text, BSS, Data段在编译时已经决定了进程将占用多少VM。可以通过size,知道这些信息。

# gcc example_2_3.c -o example_2_3
# size example_2_3
text data bss dec hex filename
1403 272 8 1683 693 example_2_3




酷毙
1

雷人

鲜花
1

鸡蛋

漂亮

刚表态过的朋友 (2 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部