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的内存,而不是我们真正需要的内存?

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

相关内容

热门资讯

强对流天气预警:辽宁福建广东台... 转自:央视网央视网消息:据中国天气网消息,中央气象台7月5日18时继续发布强对流天气蓝色预警:  预...
【硅锰】矿强托底,硅锰稳中有进... 淡季之下,本周硅锰市场也显现出一定偏强态势,但自身还是较缺乏有效利多驱动,市场跟涨情绪谨慎(钢厂虽有...
金志文×李雪琴破次元联动!未知... 未知旅行音乐节官宣惊喜嘉宾金志文、李雪琴即将加盟7月13日演出“音乐+喜剧”破次元联动是硬核弹唱还是...
内蒙古大型绿氢项目撤销 (转自:能源知库)近日,据内蒙古包头市达茂旗发改委的文件显示,内蒙古基础设施开发建设有限公司风光制氢...
历史性时刻! 昨晚发生了很多大事,第一个是美国救市行动彻底开始了,川普正式签订了“大而美”法案,紧接着又传出,川普...
台风预警升级 “丹娜丝”将向台... 转自:央视网央视网消息:据中国天气网消息,中央气象台7月5日18时发布台风黄色预警:  今年第4号台...
7月5日起 国内航线燃油附加费... 转自:央视新闻  日前,多家航空公司宣布自2025年7月5日(含)起上调国内航线燃油附加费,国内航线...
一名中国公民确诊,中使馆紧急提... 据中国驻玻利维亚大使馆5日消息,近日,玻利维亚麻疹疫情加剧,确诊病例超过70例,主要集中在圣克鲁斯省...
先买后付:金融教育如何破除债务... 来源:世界经济论坛先买后付(BNPL)正在推动在线购物,金融教育必须跟上金融科技创新的步伐。图片来源...
特朗普:应对制裁,普京很“专业... 据俄罗斯卫星通讯社、塔斯社报道,美国总统特朗普当地时间4日称,俄方一直能够应对制裁,他还称俄罗斯总统...