Linux性能学习(2.2):内存_进程线程内存分配机制探究
创始人
2024-05-28 22:09:41
0

文章目录

  • 1 进程内存分配探究
    • 1.1 代码
    • 1.2 试验过程
  • 2 线程内存分配探究
    • 2.1 代码
    • 2.2 试验过程
  • 3 总结

参考资料:
1. 嵌入式软件开发杂谈(3):Linux下内存与虚拟内存
2. 嵌入式软件开发杂谈(1):Linux下最大能创建多少线程?

在链接1中,我们可以了解到系统为每一个进程分配了4GB的虚拟内存空间,其中3GB为用户空间,是每个进程独有的,1GB为内核空间,所有的进程以及内核共同享有。

在链接2中,我们了解到系统为每个线程分配独立的堆栈,不同的系统有不同的大小,在32位linux系统上默认为8MB。

在上篇文章中介绍了系统以及进程相关的内存指标,但是有个疑问,当进程运行时候,系统是如何来分配内存的,是直接分配3GB给到内存,还是按需分配,最大3GB,通过下面代码来探究一番。

PS:下面测试环境为Ubuntu 64位系统。

1 进程内存分配探究

1.1 代码

#include 
#include int main()
{int ch = 0;int s32Size = 1024;char* s8Ptr = NULL;int s32Cnt = 0;while ((ch = getchar()) != EOF){printf("get char,malloc %d mem\n", s32Size);s8Ptr = NULL;s8Ptr = (char*)malloc(s32Size);if (NULL == s8Ptr){printf("malloc err\n");}else{printf("malloc success, cnt:%d, addr:%p\n", ++s32Cnt, s8Ptr);}}return 0;
}

上面代码,每当我们在终端输入一个字符,程序就申请1KB的内存,并且打印申请内存的地址。

1.2 试验过程

我们知道,堆是负责动态内存的分配,因此可以通过 # cat /proc/$(pid)/maps | grep heap
来查看进程的内存分配情况。

运行程序,然后使用top查看虚拟内存的使用情况以及使用上面指令来查看堆的使用情况。
在这里插入图片描述

# cat /proc/11031/maps | grep heap
00ae2000-00b03000 rw-p 00000000 00:00 0 

从上面可以可以看到这个进程的虚拟内存使用量为4352KiB,堆的地址为00ae2000-00b03000,换算一下堆的大小为132KB。但是此时程序并没有申请内存,怎么回事?

我们第一次申请内存,打印如下:

get char,malloc 1024 mem
malloc success, cnt:1, addr:0xae2830

然后查看虚拟内存VIRT使用量,还是4352KiB,并没有增加,堆的使用地址还是00ae2000-00b03000,也没有改变。

继续申请内存:

get char,malloc 1024 mem
malloc success, cnt:2, addr:0xae2c40
get char,malloc 1024 mem
malloc success, cnt:3, addr:0xae3050

第二次和第三次申请内存,VIRT和堆的信息仍然维持原状,没有改变,继续申请:

get char,malloc 1024 mem
malloc success, cnt:128, addr:0xb02c20

直到第128次申请内存时候,VIRT的使用量为4484KiB,比4352增加了132KB,而堆的使用量为264KB,比上次增加了132KB,信息如下:
在这里插入图片描述

cat /proc/11031/maps | grep heap
00ae2000-00b24000 rw-p 00000000 00:00 0                                  [heap]

继续申请内存,直到第258次申请内存,VIRT变为4616K,比4484增加了132KB,而堆的使用量为396KB,比上次增加了132KB,信息如下:

get char,malloc 1024 mem
malloc success, cnt:258, addr:0xb23c40

在这里插入图片描述

# cat /proc/11031/maps | grep heap
00ae2000-00b45000 rw-p 00000000 00:00 0                                  [heap]

从上面的测试中,我们看到第二次申请内存的地址为0xae2c40,而第一次申请内存的地址为0xae2830,两者相减,为1040,但是我们只申请了1024个字节,为什么会多16个字节?
第一个问题:为什么系统分配的内存比实际申请的内存大16个字节?

然后,我们可以看到,当程序运行时候,系统已经先为程序分配了132KB的内存,在随后我们申请内存时候,一直使用的是系统预先申请的132KB内存,直到我们申请的内存超过132KB,然后系统再次申请132KB,而不是我们需要多少就申请多少?
第二个问题:为什么系统会给进程申请132KB的内存,而不是我们真正需要的内存?

2 线程内存分配探究

2.1 代码

#include 
#include 
#include 
#include 
#include void *fun(void *arg)
{printf("----->thread_test\n");prctl(PR_SET_NAME, "thread_test");int ch = 0;int s32Size = 1024;char* s8Ptr = NULL;int s32Cnt = 0;while ((ch = getchar()) != EOF){printf("get char,malloc %d mem\n", s32Size);s8Ptr = NULL;s8Ptr = (char*)malloc(s32Size);if (NULL == s8Ptr){printf("malloc err\n");}else{printf("malloc success, cnt:%d, addr:%p\n", ++s32Cnt, s8Ptr);}}
}int main()
{int s32Ret = 0;pthread_t thread;if (getchar() != EOF){s32Ret = pthread_create(&thread, NULL, fun, NULL);		printf("pthread_create, ret:%d\n", s32Ret);}while(1) sleep(10);return 0;
}

上面代码,当我们第一次输入一个字符,则创建线程,随后再次输入字符则是分配内存

2.2 试验过程

运行程序,查看VIRT为6520KB,如下:
在这里插入图片描述

maps信息如下:
在这里插入图片描述

然后我们创建线程,查看VIRT和maps信息如下:
在这里插入图片描述
在这里插入图片描述

可以看到,VIRT由6520增加到14716,即增加了8MB,这个8MB是系统为每个线程创建时分配的。
然后开始第一次分配内存,VIRT和maps信息如下:
在这里插入图片描述
在这里插入图片描述

可以看到,当我们第一次申请内存的时候,VIRT由14716增加到80252,即系统为线程申请了64MB内存,而不是给进程分配的132KB内存。
第三个问题:为什么系统会给线程申请64MB的内存,而不是我们真正需要的内存?

开始第二次申请内存,VIRT和maps数据均没有变化,和进程中的分配机制一样,先从已经分配的内存中使用,当超过已经分配的内存时,才会重新分配新的内存。

get char,malloc 1024 mem
malloc success, cnt:1, addr:0x7f9bac0008c0get char,malloc 1024 mem
malloc success, cnt:2, addr:0x7f9bac000cd0

上面是程序的打印信息,可以看到我们申请了1024字节的内存,但是系统还是分配了1040个字节的内存,即多分配了16字节的内存,和问题1一致。

3 总结

通过上面的测试,我们得出了三个问题:

  • 第一个问题:64位系统,为什么系统分配的内存比实际申请的内存大16个字节?
  • 第二个问题:64位系统,为什么系统会给进程申请132KB的内存,而不是我们真正需要的内存?
  • 第三个问题:64位系统,为什么系统会给线程申请64MB的内存,而不是我们真正需要的内存?

后面章节将解决这几个问题。

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...