zl程序教程

您现在的位置是:首页 >  系统

当前栏目

【Linux 内核 内存管理】内存管理架构 ⑤ ( sbrk 内存分配系统调用代码示例 | 在 /proc/pid/maps 中查看进程堆内存详情 )

2023-09-14 09:07:27 时间


本篇博客调用 sbrk 系统调用函数 , 申请并修改 堆内存 , 并在 /proc/pid/maps 中查看该进程的 堆内存 ;





一、sbrk 内存分配系统调用代码示例



sbrk 系统调用函数 , 作用是 修改程序 BSS 段大小 ;

函数原型如下 :

#include <unistd.h>  
int brk(void *addr);  
void *sbrk(intptr_t increment);  

函数执行成功 , 返回一个指向 " 堆内存 " 的指针 ;

函数执行失败 , 返回 (void*)-1 返回值 ;


内存地址查找 : 先获取 当前运行的 进程 ID , 也就是 PID , 然后根据 PID 找到 内存地址 ; 如果进程退出 , 也就获取不到 进程的 信息了 , 这里需要有一个死循环 , 保证进程一直存活 ;

	// 此处死循环阻塞, 方便查看 /proc/pid/maps 中的信息
	// 进程退出后 , 进程相关内存信息也会同时销毁
    while (1);

完整代码示例 :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	// 使用 sbrk 系统调用申请 堆内存
    int *p = sbrk(0);

	// 记录该堆内存地址
    int *p_old = p;

	// 继续为 申请的堆内存, 申请 1024 字节内存
    p = sbrk(1024);

	// 打印进程 ID , PID 
    printf("pid : %d\n", getpid());
    
	// 打印 申请的 堆内存地址 , 发现地址没有变化
    printf("p_old : %p \np : %p \n", p_old, p);

	// 申请新的 堆内存
    int *p_new = sbrk(0);

	// 打印新的 堆内存地址
    printf("p_new : %p\n", p_new);

	// 此处死循环阻塞, 方便查看 /proc/pid/maps 中的信息
	// 进程退出后 , 进程相关内存信息也会同时销毁
    while (1);
    return 0;
}

函数打印结果 :

han@ubuntu:~/vscode/memory$ gcc memory.c 
han@ubuntu:~/vscode/memory$ ./a.out 
pid : 4829
p_old : 0x203e000 
p : 0x203e000 
p_new : 0x2060000

在这里插入图片描述

进程 ID 为 4829 4829 4829 ;

sbrk 返回的指针 p , 在第二次申请内存时 , 指针始终没有改变 , 一直都是 0x203e000 地址 ;

如果使用新的指针 p_new 接收 sbrk 系统调用返回的堆内存指针 , 则分配的是新的地址 ;





二、在 /proc/pid/maps 中查看进程堆内存详情



在上一节 , 已经打印出进程的 PID 为 4829 4829 4829 , 根据该 PID , 可以直接获取该进程的内存情况 ,

执行

cat /proc/4829/maps

命令 , 可以打印出指定进程 ID 的内存映射情况 , 打印结果如下 :

han@ubuntu:~/vscode/memory$ cat /proc/4829/maps
00400000-00401000 r-xp 00000000 08:01 3147969                            /home/han/vscode/memory/a.out
00600000-00601000 r--p 00000000 08:01 3147969                            /home/han/vscode/memory/a.out
00601000-00602000 rw-p 00001000 08:01 3147969                            /home/han/vscode/memory/a.out
0203e000-02060000 rw-p 00000000 00:00 0                                  [heap]
7f3534a9f000-7f3534c5f000 r-xp 00000000 08:01 1723650                    /lib/x86_64-linux-gnu/libc-2.23.so
7f3534c5f000-7f3534e5f000 ---p 001c0000 08:01 1723650                    /lib/x86_64-linux-gnu/libc-2.23.so
7f3534e5f000-7f3534e63000 r--p 001c0000 08:01 1723650                    /lib/x86_64-linux-gnu/libc-2.23.so
7f3534e63000-7f3534e65000 rw-p 001c4000 08:01 1723650                    /lib/x86_64-linux-gnu/libc-2.23.so
7f3534e65000-7f3534e69000 rw-p 00000000 00:00 0 
7f3534e69000-7f3534e8f000 r-xp 00000000 08:01 1723642                    /lib/x86_64-linux-gnu/ld-2.23.so
7f3535074000-7f3535077000 rw-p 00000000 00:00 0 
7f353508e000-7f353508f000 r--p 00025000 08:01 1723642                    /lib/x86_64-linux-gnu/ld-2.23.so
7f353508f000-7f3535090000 rw-p 00026000 08:01 1723642                    /lib/x86_64-linux-gnu/ld-2.23.so
7f3535090000-7f3535091000 rw-p 00000000 00:00 0 
7ffc4ac84000-7ffc4aca5000 rw-p 00000000 00:00 0                          [stack]
7ffc4ad19000-7ffc4ad1d000 r--p 00000000 00:00 0                          [vvar]
7ffc4ad1d000-7ffc4ad1f000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
han@ubuntu:~/vscode/memory$ 

在这里插入图片描述

第一次使用 sbrk 申请的内存地址是 0x203e000 ,

第二次还是为 p 指针申请内存 , 实际上是修改 " 堆内存 " 大小 , 其指针的首地址不变 , 是 0x203e000 ;

第三次调用 sbrk 申请的是新的内存 , 地址是 0x2060000 ;


/proc/4829/maps 文件中 , 堆内存的区域是 0203e000-02060000 , 与打印出的值相对应 ;

0203e000-02060000 rw-p 00000000 00:00 0                                  [heap]