关于内存分配与页大小的理解是否正确?相关技术疑问
关于内存分配与页大小的疑问
我编写了一段用于检查进程段边界的代码,运行后得到对应输出。发现无论分配1字节还是1024字节,sbrk(0)均返回0x557f00b30000,推测内存按页而非精确请求分配,但两次sbrk值差值为132K,疑惑该值是否为页大小,以及如何确认页大小,同时想确认我对内存分配与页大小的理解是否正确。
代码
#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <stdbool.h> #include <fcntl.h> extern char edata, etext, end; void dump(void) { printf("etext=%p, edata=%p, end=%p, sbrk(0)=%p\n", &etext, &edata, &end, sbrk(0)); } int main(void) { dump(); char *p = (char*)malloc(1); printf("allocated 1 byte\n"); dump(); free(p); p = (char*)malloc(1024); printf("allocated 1024 bytes\n"); dump(); free(p); return 0; }
运行输出
>./a.out etext=0x557f00098305, edata=0x557f0009b010, end=0x557f0009b018, sbrk(0)=0x557f00b0f000 allocated 1 byte etext=0x557f00098305, edata=0x557f0009b010, end=0x557f0009b018, sbrk(0)=0x557f00b30000 allocated 1024 bytes etext=0x557f00098305, edata=0x557f0009b010, end=0x557f0009b018, sbrk(0)=0x557f00b30000
解答
你的核心推测方向是对的,但132K并非系统页大小,下面逐一解释:
1. 为什么两次malloc后sbrk(0)不变
malloc是用户态内存分配器,不会每次请求都直接调用sbrk向内核申请内存。第一次调用malloc(1)时,malloc会一次性向内核申请一块远大于1字节的内存块作为缓存,后续malloc(1024)直接从缓存中分配空间,因此sbrk(0)不会发生变化。
2. 132K差值的由来
这个差值是malloc首次向内核申请的堆空间总大小,并非系统页大小。malloc会结合系统页大小、内存对齐规则以及自身的管理开销(比如块描述符、对齐padding等),确定初始申请的内存块规模。
3. 确认系统页大小的方法
- 命令行方式:执行
getconf PAGESIZE,直接输出系统页大小(常见值为4K或8K) - 代码方式:调用
sysconf(_SC_PAGESIZE)接口(需包含<unistd.h>头文件),示例:#include <unistd.h> #include <stdio.h> int main() { printf("Page size: %ld bytes\n", sysconf(_SC_PAGESIZE)); return 0; } - 系统文件查看:查看
/proc/cpuinfo文件中的pagesize字段(部分Linux系统有效)
4. 关于内存分配与页大小的理解确认
- 内核层面:内核给进程分配内存时,确实以页为最小单位,哪怕只需要1字节,内核也会分配至少一页内存。
- 用户态层面:
malloc作为用户态分配器,会在堆上管理这些页,将大的页拆分成小块供用户使用,避免频繁向内核申请内存,提升分配效率。 - 内存释放:调用
free时,malloc通常不会立刻将内存还给内核,而是保留在自身缓存中,供后续malloc请求复用,因此free后sbrk(0)不会立刻回落。
内容的提问来源于stack exchange,提问作者my_question
相关产品推荐
相关产品推荐

