Linux性能学习(2.3):内存_为什么分配的内存比申请的内存大16个字节
创始人
2024-05-28 21:28:15
0

文章目录

  • 1 验证申请不同内存,系统分配机制
    • 1.1 代码
    • 1.2 测试
    • 1.3 结论
  • 2 为什么会多分配内存
  • 3 为什么会有4字节不可使用

参考资料:

  1. https://www.gnu.org/software/libc/

在上一篇文章中,探讨了Linux系统对进程以及线程的内存分配问题,然后采用申请1KB内存的方式进行验证,然后发现将第二次申请的内存地址减去第一次申请内存的地址,长度为1040,比我们申请的1024多了16个字节,从而提出一个问题,“在64位系统中,为什么系统分配的内存比实际申请的内存大16个字节?”。

但是上一篇的文章主要是探讨内存分配的,所以对这个问题没有过多追究,提出这个问题也不严谨,因为只是申请了1024个字节,系统分配了1040,多了16个字节,那么如果申请1个字节、2个字节、3个字节等等,系统又是如何分配的,是否还是多分配16字节?64位系统和32位系统是否都是多分配16字节?

所以下面我们先验证下,如果我们申请不同大小的内存,系统是否还是会多申请16字节的内存?

1 验证申请不同内存,系统分配机制

1.1 代码

#include 
#include int main()
{int i = 0;char* s8New = NULL;char* s8Old = malloc(0);if (NULL == s8Old){printf("malloc err\n");}else{printf("malloc success, malloc size:%d, usable_size:%d, addr:%p, ", 0, malloc_usable_size(s8Old), s8Old);}for (i = 1; i < 20480; i++){	s8New = (char*)malloc(i);if (NULL == s8New){printf("malloc err\n");}if ((NULL != s8New) && (NULL !=  s8Old)){printf("addr size:%d\n", s8New - s8Old);s8Old = s8New;printf("malloc success, malloc size:%d, usable_size:%d, addr:%p, ", i, malloc_usable_size(s8Old), s8Old);}else{printf("malloc success, malloc size:%d, usable_size:%d, addr:%p, ", i, malloc_usable_size(s8New), s8New);}}return 0;
}

上述代码的功能是从1个字节开始,逐步增加,直到申请2MB的内存,查看系统分配情况,会有三个主要参数的打印:“malloc size”表示我们申请的内存,“usable_size”是使用malloc_usable_size来获取系统实际分配的大小,“addr size”为下一个申请的内存地址减去当前申请内存的地址,即为当前申请内存的大小。

1.2 测试

在Ubuntu 64位系统下测试,结果如下:
在这里插入图片描述

在32位系统下测试,结果如下:
在这里插入图片描述

上面的数据,只是部分数据,经过综合,得出如下数据:
64位系统
在这里插入图片描述

32位系统
在这里插入图片描述

1.3 结论

通过上面的表格,我们可以得出如下结论:

  • A.在我们申请内存的时候,系统可能会申请多的内存给到我们,具体规则是:
    32位系统下:N8+4,N为1~无穷大,(N8+4)的值为最接近与我们申请的内存的值;
    64位系统下:N16+8,N为1~无穷大,(N16+8)的值为最接近与我们申请的内存的值。
  • B.申请的内存的地址相减会比实际申请的内存usable_size还要大,在32位系统下大4个字节,在64位系统下大8个字节。即实际分配的内存地址范围大小为:
    32位系统下:N8+8;
    64位系统下:N
    16+16。

2 为什么会多分配内存

针对上面的结论A,我们进行分析查找原因。

在上面我们使用malloc来申请内存,那么这些问题就跟malloc有关了,我们查看下malloc相关的代码,看看有啥收获。

源码可通过上面参考链接进行下载,在malloc.c/_int_malloc函数中,我们看到了checked_request2size函数,它的作用是将我们需要申请的字节大小转换为内部的大小,通过字节对齐等方式进行转换,来获取最小MINSIZE(最小可分配大小)的大小。
在这里插入图片描述

在这里,我们得到了一个信息MINSIZE,我们进到checked_request2size函数里面进行查看,
在这里插入图片描述

在checked_request2size中的request2size中我们可以看到,如果 (req) + SIZE_SZ + MALLOC_ALIGN_MASK的大小小于MINSIZE,那么就返回MINSIZE,如果大于,则进行对齐操作,再返回。
现在我们获取到结果宏参数:SIZE_SZ、MALLOC_ALIGN_MASK、MINSIZE

SIZE_SZ的大小通过代码追踪就是unsigned int的长度,在32位系统中就是4个字节;
MALLOC_ALIGN_MASK相关的定义如下:

/* The corresponding bit mask value.  */
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
/* MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.  Itmust be a power of two at least 2 * SIZE_SZ, even on machines forwhich smaller alignments would suffice. It may be defined as largerthan this though. Note however that code and data structures areoptimized for the case of 8-byte alignment.  */
#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \? __alignof__ (long double) : 2 * SIZE_SZ)

可以得出,MALLOC_ALIGNMENT在32位系统中的长度为2*SIZE_SZ,即长度为8,那么MALLOC_ALIGN_MASK的长度就为7了。
MINSIZE的相关定义如下:

#define MINSIZE  \(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))

MIN_CHUNK_SIZE 展开如下:

#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
===》等价于
#define MIN_CHUNK_SIZE (size_t) & ((struct malloc_chunk*)NULL) -> fd_nextsize)

struct malloc_chunk的定义如下:

struct malloc_chunk {INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */struct malloc_chunk* fd;         /* double links -- used only if free. */struct malloc_chunk* bk;/* Only used for large blocks: pointer to next larger size.  */struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */struct malloc_chunk* bk_nextsize;
};

所以上面代码的大致意思是,取malloc_chunk中fd_nextsize的地址,这样得到的地址就是这个成员在结构体中的首地址。所以这个结构体中,必须需要的是前4个,后面两个仅用于large blocks,所以在32位的系统中,这个结构体的大小为44=16字节,在64位上为84=32位,或者4+4+8+8=24位。
由此,可以得到:

#define MINSIZE =(((16+7) & ~7))=16。

至此,我们可以得出如下信息,在32位系统中,一些参数值如下:

SIZE_SZ 4
MALLOC_ALIGNMENT 2*4=8
MALLOC_ALIGN_MASK 8-1=7
MIN_CHUNK_SIZE 16
MINSIZE 16

那么request2size宏定义可以换算如下:

#define request2size(req)       (((req) + 4 + 7 < 16)  ? 16 :                                                       ((req) + 4 + 7) & ~7)

将上面1.2章节中32位申请的内存对照表和上面的request2size中进行对照,结论一致。

同理,在64位系统中,一些参数值如下:

SIZE_SZ 8
MALLOC_ALIGNMENT 2*8=16
MALLOC_ALIGN_MASK 16-1=15
MIN_CHUNK_SIZE 32
MINSIZE 32

至此,我们可以得出结论,当我们申请内存时候,系统会根据自身的机制分配大于我们申请的内存的大小,具体分配大小参考request2size进行确认。

3 为什么会有4字节不可使用

针对问题B进行分析,在上面,我们看到在32位系统中,addr size比实际可使用的内存大小usable_size大4个字节,为什么会有这4个字节的浪费,或者说不能使用?

在malloc.c中有如下解释:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上面的解释大致如下:
我们申请的chunk主要由Size of previous chunk + Size of chunk+user data等几部分构成的,chunk指针指向chunk开始的地方,mem指针是提供给用户的指针地址,从这个这个地址可以使用,进行读写等操作。
在这里插入图片描述

空闲的chunk是存储是双向循环链表中的,结构体是由 Size of previous chunk + Size of chunk+fd+bk等4部分组成的,参考下图:
在这里插入图片描述

上面的A/M/P三个参数:

  • P:如果P为0,表示前一个chunk为空闲,则prev_size中的值才有效,表示上一个空闲chunk的大小;如果P为1,则前一个chunk正在使用,prev_size无效。
  • M:如果为1,则是通过mmap方式分配的内存;如果为0,则是通过heap方式分配的内存。
  • A:为0表示主分区分配的内存;为1表示非主分配区分配的内存。

通过上图可以看到,一个chunk有head和foot,都是表示当前chunk大小,但是foot已经在next chunk了,即next chunk的Size of previous chunk ,同时为了提高chunk的有效载荷数据,Size of previous chunk 这个数据段也会用来存储数据,所以一个chunk可以由head+mem两部组成。而head的长度为SIZE_SZ的长度,即4个字节。

所以可以理解为,在32位系统下,linux申请的内存减去4个字节的长度,剩下的长度均为有效数据长度,即我们可以使用的长度。

同理,在64位系统下,linux申请的内存减去8个字节的chunk size字段,剩下的便是可以使用的数据长度。

相关内容

热门资讯

债市调整影响投资收益 上市银行... 42家A股上市银行一季度业绩已全部“放榜”,其中30家净利润实现正增长。总体来看,上市银行盈利主要是...
释放消费潜力 专家建议宏观政策... 近日,中国宏观经济论坛(CMF)季度论坛(2025年第一季度)在京举行。论坛聚焦“积极进取的中国宏观...
从严从实从细保平安保畅通 用心... 本报讯(记者 田得乾 石成砚)5月5日,省委副书记、省长罗东川来到省交通运输厅、省公安厅,调研调度全...
杭州楚环科技股份有限公司关于持... 证券代码:001336 证券简称:楚环科技 公告编号:2025-018杭州楚环科技股份有限公司关于...
“一票游多日”折射旅游业向链式... 转自:千龙网这个五一假期,游客发现很多景区有了新变化。现在国内许多景点都开始实行“一票游多日”的制度...
一片野茶林托起山村共富路 转自:衢州日报  本报讯 (报道组 郑晨 童彤 通讯员 谭君华) “茶叶种植在深山,清明谷雨芽发青…...
贵州百灵企业集团制药股份有限公... 证券代码:002424 证券简称:ST百灵 公告编号:2025-024贵州百灵企业集团制药股份有限公...
上市银行一季度业绩整体承压 债市调整影响投资收益上市银行一季度业绩整体承压◎记者 马慜 42家A股上市银行一季度业绩已全部“放榜...
A股风险偏好有望回暖 5月或回... ■机构展望A股风险偏好有望回暖5月或回归科技成长风格◎记者 汪友若 5月6日,A股市场迎来5月首个交...
建立完善监管体系 促进低空经济... 党的二十届三中全会提出,完善推动新一代信息技术、人工智能、航空航天、新能源、新材料、高端装备、生物医...
存量强势吸金 新品密集成立 今... 存量强势吸金 新品密集成立今年以来2700亿元资金借道ETF入市◎记者 赵明超 尽管开年以来遭遇资金...
东方时尚驾驶学校股份有限公司关... 证券代码:603377 证券简称:ST东时(维权) 公告编号:临2025-073转债代码:11357...
人气旺 市面暖 活力足 转自:衢州日报  文旅融合热力上扬,消费市场活力涌动,电影文博持续火热……今年“五一”,各地假日经济...
汇卡商务等机构违规被罚 第三方... 第三方支付行业加快洗牌。近日,包括北京市政交通一卡通、广东汇卡商务等在内的多家机构因违规被处罚。中国...
将对所有在外国制作的电影征收1... 转自:成都日报锦观特朗普:将对所有在外国制作的电影征收100%关税 据新华社洛杉矶5月4日电(...
“拎包入住”模式引领种菜新潮 转自:衢州日报  记者 林敏 文/摄 报道组 郑晨  4月29日下午,位于柯城区信安街道信安村的信安...
丝瓜络种植正当时 转自:衢州日报  ​气温持续回升,正是农作物育苗种植的关键时节。近日,在常山县东案乡金源村,5万株丝...
兵团研发成功葡萄藤越冬新覆盖材... 本报石河子讯(全媒体记者 马燕) “这片试验田同时采用传统埋土法、毛毡覆盖法和我们新研发的‘抗冻...
为教育后勤服务升级赋能 转自:衢州日报  本报讯 (通讯员 雷湘熠) 近日,杭州市富阳区教育局组织2025年教育系统后勤管理...
经济迸活力 文旅引热潮 转自:成都日报锦观经济迸活力 文旅引热潮 近日,全国首单知识产权质押关税保函落地成都高新区。企...