经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
malloc中的系统调用brk和mmap
来源:cnblogs  作者:一生热爱  时间:2021/6/7 9:14:58  对本文有异议

malloc中的系统调用brk和mmap

环境
  • ubuntu14.04

  • 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_brkbrk同时指向data/bss段的结束位置(end_data)
    • 当ASLR打开时,start_brk和brk同时指向data/bss段的结束位置(end_data)再加上一个随机的brk偏移。
  • 上面的进程虚拟内存布局展示了,start_brk是堆段的开始位置 ,brk(program break)是堆栈的结束位置。

例子

  1. /* sbrk, brk 例子 */
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. int main()
  6. {
  7. void *curr_brk, *tmp_brk = NULL;
  8. printf("Welcome to sbrk example:%d\n", getpid());
  9. /* sbrk(0) 获取当前 program break 位置 */
  10. tmp_brk = curr_brk = sbrk(0);
  11. printf("Program Break Location1:%p\n", curr_brk);
  12. getchar();
  13. /* 使用 brk 增加 program break 位置 */
  14. brk(curr_brk+4096);
  15. curr_brk = sbrk(0);
  16. printf("Program break Location2:%p\n", curr_brk);
  17. getchar();
  18. /* 使用 brk 减小 program break 位置 */
  19. brk(tmp_brk);
  20. curr_brk = sbrk(0);
  21. printf("Program Break Location3:%p\n", curr_brk);
  22. getchar();
  23. return 0;
  24. }
  • 在增加program break之前,输出如下:

  • start_brk=brk=end_data=0x602000

  • 在增加program break之后,输入如下:

  • start_brk=end_data=0x602000,brk=0x603000.

  • 可以观察到堆段

  1. 00602000-00603000 rw-p 00000000 00:00 0 [heap]
  • 00602000-00603000是堆段的虚拟地址范围
  • rw-p的标准含义是Read、Write、 NoeXecute、Private
  • 00000000 是文件偏移量,由于没有映射任何文件所以为0
  • 00:00 是major/minor device number,由于没有映射任何文件所以为0
  • 0是inode 也是没有映射任何文件所以为0
  • 【heap】是堆段

mmap

  • malloc使用mmap创建一个私有匿名的映射段,这个映射段的主要目的是申请一块(零值初始化的)新内存,并且这块内存只能被调用的这个进程独占使用。
  1. /* 使用mmap系统调用做私有匿名映射的例子 */
  2. #include <stdio.h>
  3. #include <sys/mman.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. void static inline errExit(const char* msg)
  10. {
  11. printf("%s failed. Exiting the process\n", msg);
  12. exit(-1);
  13. }
  14. int main()
  15. {
  16. int ret = -1;
  17. printf("Welcome to private anonymous mapping example::PID:%d\n", getpid());
  18. printf("Before mmap\n");
  19. getchar();
  20. char* addr = NULL;
  21. addr = mmap(NULL, (size_t)132*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  22. if (addr == MAP_FAILED)
  23. errExit("mmap");
  24. printf("After mmap\n");
  25. getchar();
  26. /* Unmap mapped region. */
  27. ret = munmap(addr, (size_t)132*1024);
  28. if(ret == -1)
  29. errExit("munmap");
  30. printf("After munmap\n");
  31. getchar();
  32. return 0;
  33. }
  • 调用mmap之前:可以看到,属于libc.so和ld-linux.so共享库的内存映射段。

  • 调用mmap之后:如下我们可以看到,mmap映射的内存段已经从上图红色框内分配出去(0xe0000-0xbf000=0x21000).

  • 调用munmap之后,如下输出可以看到mmap已经被解除映射了。

原文链接:http://www.cnblogs.com/binarysystemloophole/p/14849348.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号