内容简介:阅读本文前你可能已经知道,malloc通过系统调用的方式从操作系统申请内存。事实上,malloc内部是通过系统调用
阅读本文前你可能已经知道,malloc通过系统调用的方式从操作系统申请内存。事实上,malloc内部是通过系统调用 brk 或 mmap 来申请内存的。如下面的进程虚拟内存布局图所示,mmap对应 Memory Mapping Segment
,brk对应 Heap
。
brk
brk 通过增加program break的位置( brk )从内核申请(非零值初始化的)内存。一开始,堆段(heap segment)的起始位置( start_brk )和结束位置( brk )指向同一个位置:
- 当 ASLR (Address Space Layout Randomization)关闭时,
start_brk
和brk同时指向data/bss
段的结束位置( end_data )。 - 当ASLR打开时,
start_brk
和brk同时指向data/bss
段的结束位置(end_data
)再加上一个随机的brk偏移。
上面的进程虚拟内存布局图展示了,start_brk是堆段的开始位置,brk(program break)则是堆段的结束位置。
例子:
/* sbrk, brk 例子 */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { void *curr_brk, *tmp_brk = NULL; printf("Welcome to sbrk example:%d\n", getpid()); /* sbrk(0) 获取当前 program break 位置 */ tmp_brk = curr_brk = sbrk(0); printf("Program Break Location1:%p\n", curr_brk); getchar(); /* 使用 brk 增加 program break 位置 */ brk(curr_brk+4096); curr_brk = sbrk(0); printf("Program break Location2:%p\n", curr_brk); getchar(); /* 使用 brk 减小 program break 位置 */ brk(tmp_brk); curr_brk = sbrk(0); printf("Program Break Location3:%p\n", curr_brk); getchar(); return 0; }
在增加program break之前,输出如下:
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ ./sbrk Welcome to sbrk example:6141 Program Break Location1:0x804b000 ... sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6141/maps ... 0804a000-0804b000 rw-p 00001000 08:01 539624 /home/sploitfun/ptmalloc.ppt/syscalls/sbrk b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
-
start_brk=brk=end_data=0x804b000
此时没有堆段。
译者yoko注,这里通过 cat /proc/<pid>/maps
的方式查看进程映射的内存区域,输出的含义下文会具体讲
在增加program break之后,输出如下:
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ ./sbrk Welcome to sbrk example:6141 Program Break Location1:0x804b000 Program Break Location2:0x804c000 ... sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6141/maps ... 0804a000-0804b000 rw-p 00001000 08:01 539624 /home/sploitfun/ptmalloc.ppt/syscalls/sbrk 0804b000-0804c000 rw-p 00000000 00:00 0 [heap] b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
start_brk=end_data=0x804b000 brk=0x804c000
可以观察到堆段。
其中 0804b000-0804c000 rw-p 00000000 00:00 0 [heap]
的含义:
-
0804b000-0804c000
是这个堆段的虚拟地址范围。 -
rw-p
标准的含义是Read, Write, NoeXecute, Private
-
00000000
是文件偏移量,由于并没有映射任何文件,所以为零 -
00:00
是major/minor device number,由于并没有映射任何文件,所以为零 -
0
是inode,由于并没有映射任何文件,所以为零 -
[heap]
是堆段
mmap
malloc使用 mmap 创建一个私有匿名的映射段。这个映射段的主要目的是申请一块(零值初始化的)新内存,并且这块内存只能被调用的这个进程独占使用。
例子:
/* 使用mmap系统调用做私有匿名映射的例子 */ #include <stdio.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> void static inline errExit(const char* msg) { printf("%s failed. Exiting the process\n", msg); exit(-1); } int main() { int ret = -1; printf("Welcome to private anonymous mapping example::PID:%d\n", getpid()); printf("Before mmap\n"); getchar(); char* addr = NULL; addr = mmap(NULL, (size_t)132*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) errExit("mmap"); printf("After mmap\n"); getchar(); /* Unmap mapped region. */ ret = munmap(addr, (size_t)132*1024); if(ret == -1) errExit("munmap"); printf("After munmap\n"); getchar(); return 0; }
调用mmap之前:如下输出我们可以看到,只有属于 libc.so
和 ld-linux.so
共享库的内存映射段。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
调用mmap之后:如下输出我们可以观察到,我们mmap映射的内存段( b7e00000–b7e21000
,大小是132KB)和已经存在的内存映射段( b7e21000–b7e22000
)合并了(变成 b7e00000-b7e22000
)。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e00000-b7e22000 rw-p 00000000 00:00 0 ...
其中 b7e00000-b7e22000 rw-p 00000000 00:00 0
的含义:
b7e00000-b7e22000 rw-p is Flags (Read, Write, NoeXecute, Private) 00000000 00:00 0
调用munmap之后:如下输出我们可以看到,mmap映射的内存段已经被解除映射了,换言之,相应的已归还给操作系统。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
注意:我们以上所做实验,ASLR是关闭的。
英文原文地址: https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc/
原文链接: https://pengrl.com/p/20032/
原文出处: yoko blog ( https://pengrl.com )
原文作者: yoko ( https://github.com/q191201771 )
版权声明:本文欢迎任何形式转载,转载时完整保留本声明信息(包含原文链接、原文出处、原文作者、版权声明)即可。本文后续所有修改都会第一时间在原始地址更新。
以上所述就是小编给大家介绍的《[译] malloc中的系统调用brk和mmap》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
图片转BASE64编码
在线图片转Base64编码工具
XML、JSON 在线转换
在线XML、JSON转换工具