[译] malloc中的系统调用brk和mmap

栏目: IT技术 · 发布时间: 4年前

内容简介:阅读本文前你可能已经知道,malloc通过系统调用的方式从操作系统申请内存。事实上,malloc内部是通过系统调用

阅读本文前你可能已经知道,malloc通过系统调用的方式从操作系统申请内存。事实上,malloc内部是通过系统调用 brkmmap 来申请内存的。如下面的进程虚拟内存布局图所示,mmap对应 Memory Mapping Segment ,brk对应 Heap

[译] malloc中的系统调用brk和mmap

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.sold-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


以上所述就是小编给大家介绍的《[译] malloc中的系统调用brk和mmap》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数学世纪

数学世纪

皮耶尔乔治·奥迪弗雷迪 / 胡作玄、胡俊美、于金青 / 上海科学技术出版社 / 2012-1 / 28.00元

《数学世纪:过去100年间30个重大问题》以简短可读的方式论述了整个20世纪的数学。20世纪的数学博大精深,新兴领域及学科的建立发展,许多经典问题得到解决,大量新的有意义的问题的引入,为数学带来了活力。《数学世纪:过去100年间30个重大问题》介绍了数学基础,20世纪的纯粹数学、应用和计算数学,以及目前未解的重要问题,中间穿插了希尔伯特的23个问题的解决情况、菲尔兹奖和沃尔夫奖得主的工作成就等。一起来看看 《数学世纪》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具