免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 3081 | 回复: 20

[内核入门] mmap()函数疑问? [复制链接]

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-03-11 16:18 |显示全部楼层
mmap()如果指定了要映射的虚拟区间,并且这段区间还映射着物理内存,可以用do_munmap() “Clear Old maps”,为什么?

比如用户进程通过malloc()得到200~300这块虚拟空间,并且与物理内存建立了映射关系,这时又调用mmap()希望将某个文件映射到100~1000。
① 如果这个情况下mmap()返回错误,那么mmap()就没有实际意义了,因为每次调用它,都得用户程序员自己确定一块还没有使用的虚拟空间;
② 按照mmap()函数的真实逻辑,它会先撤消200~300这段区间已有的映射,确保100~1000是“干净”的,再使用。
   进程A:malloc()得到200~300空间
   此时切换到进程B:mmap()将某个文件映射到100~1000
    此时回到进程A,往200~300写,不是会干扰到进程B吗,而且如果这个时候free(),又会怎样?

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
发表于 2016-03-13 10:21 |显示全部楼层
你不是连验证程序都没有写过。回答你的问题。
1. mmap是可以不指定虚拟地址,由内核分配的。
2. 进程A和进程B都有独立的3G用户态虚拟地址空间。互不干预。这是LInux的常识呀。

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-03-13 11:40 |显示全部楼层
回复 2# Tinnal

嗯,例子举的不对,我是想问在调用mmap()指定映射100~1000时,没办法确定这段虚拟地址是不是已经在用了,如果已经被之前调用malloc()的时候使用了,mmap()好像是把之前与物理页面的映射断开,而建立与文件的映射,不明白这样做为什么可以这样做。

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-03-13 11:46 |显示全部楼层
Tinnal 发表于 2016-03-13 10:21
你不是连验证程序都没有写过。回答你的问题。
1. mmap是可以不指定虚拟地址,由内核分配的。
2. 进程A和进 ...


我提问的时候应该是想写线程。

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
发表于 2016-03-13 21:03 |显示全部楼层
回复 4# _nosay

占对同一个进程的情况。如果你没有在mmap时没有指定MAP_FIXED, 在某一个虚拟地址已经被映射了的情况下,就算你再指定相同的地址, Linux也会重新给你分配一个不重叠的虚拟地址给你,和你直接传0进去的情况一下。

如果你采用MAP_FIXED告诉Linux你一定要映射这个地址,那Linux也没有办法,就只能解掉原来的映射罗。从mmap的man手册里就可以看到。

MAP_FIXED
Don't interpret addr as a hint: place the mapping at exactly that address. addr must be a multiple of the page size. If the memory region specified by addr and len overlaps pages of any existing mapping(s), then the overlapped part of the existing mapping(s) will be discarded. If the specified address cannot be used, mmap() will fail. Because requiring a fixed address for a mapping is less portable, the use of this option is discouraged.


   

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-03-14 06:47 |显示全部楼层
回复 5# Tinnal

那指定映射地址的应用场合有哪些,用户程序不太可能在调用mmap()的时候知道哪些虚拟地址是闲着的,和最开始的问题那样,如果mmap100~1000的时候,将malloc的200~300解除了,但这时有些指令还有可能把它当成malloc200~300使用(包括调用free()),不会出问题吗?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-14 10:59 |显示全部楼层
具体的例子一下子想不起来,貌似有些exploit代码里喜欢用MAP_FIXED(比如老版本内核里,把NULL地址映射到邪恶的用户态程序段)

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-03-14 13:19 |显示全部楼层
回复 7# nswcfd

nswcfd 你是搞邪恶的,还是反邪恶的?
我写的一个测试程序,先malloc()得到(0x9a04008, 0x9a0600,再调用mmap()映射(0x9a05000, 0x9a07000)(起始地址按页面对齐了一下,两个区间是重叠的),最后free()时程序挂了:
[116] $ ./a.out
malloc: (0x9a04008, 0x9a0600
mmap: (0x9a05000, 0x9a07000)
*** glibc detected *** ./a.out: double free or corruption (out): 0x09a04008 ***
a.out: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted (core dumped)
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/mman.h>


  4. #define PAGE_SHIFT        12
  5. #define TWO_PAGE          2*4*1024

  6. #define PAGE_SIZE         (1UL << PAGE_SHIFT)
  7. #define PAGE_MASK         (~(PAGE_SIZE-1))

  8. #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)


  9. int main()
  10. {
  11.         char *p1 = NULL;
  12.         char *p2 = NULL;

  13.         p1 = malloc(TWO_PAGE);
  14.         if (p1 == NULL) {
  15.                 printf("malloc failed\n");
  16.                 goto err;
  17.         }

  18.         printf("malloc: (%p, %p)\n", p1, p1+TWO_PAGE);

  19.         [color=Red]// 地始地址不按页面对齐,mmap()失败[/color]
  20.         p2 = mmap((void *)PAGE_ALIGN((unsigned long)p1), TWO_PAGE, PROT_WRITE, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED, -1, 0);
  21.         if (p2 == (void *)(-1)) {
  22.                 printf("mmap failed: %p\n", (void *)PAGE_ALIGN((unsigned long)p1));
  23.                 goto err;
  24.         }

  25.         printf("mmap: (%p, %p)\n", p2, p2+TWO_PAGE);

  26.         free(p1);
  27.         munmap(p2, TWO_PAGE);

  28.         return 0;
  29. err:
  30.         if (p1 != NULL)
  31.                 free(p1);
  32.         if (p2 != NULL)
  33.                 munmap(p2, TWO_PAGE);
  34.         return -1;
  35. }
复制代码

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
发表于 2016-03-14 19:51 |显示全部楼层
回复 6# _nosay

不知道你为什么一直举例malloc和你mmap冲突。 malloc使用的heap和mmaps区域,在Linux里头是有规定的。
见:http://duartes.org/gustavo/blog/ ... -program-in-memory/

内存就那么3G, 你非得用mmap不按规矩的使用,当然出问题了。 就像你不按FHS存放文件一样。没错,你可以肆意的用已有的接口去实现你另类的想法。但也得承担不按规范的结果。

在没有全局的内存规划前提下,最好的方式是addr传0, 让内核给你选。



   

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
发表于 2016-03-14 19:53 |显示全部楼层
还有:https://lwn.net/Articles/91829/

如果你想在Linux的地址空间里驰骋,请选择64位linux,把目前能用的内存mmap几次都用不完。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP