免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5648 | 回复: 9
打印 上一主题 下一主题

[内存管理] 是否malloc每次调用都会进入内核? [复制链接]

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-13 06:20:00数据库技术版块每日发帖之星
日期:2016-06-15 06:20:00数据库技术版块每日发帖之星
日期:2016-06-16 06:20:00数据库技术版块每日发帖之星
日期:2016-06-18 06:20:00程序设计版块每日发帖之星
日期:2016-06-27 06:20:00程序设计版块每日发帖之星
日期:2016-07-09 06:20:00IT运维版块每日发帖之星
日期:2016-07-15 06:20:00IT运维版块每日发帖之星
日期:2016-07-27 06:20:00程序设计版块每日发帖之星
日期:2016-08-18 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-05-05 21:43 |只看该作者 |正序浏览
本帖最后由 mordorwww 于 2014-05-05 21:44 编辑

malloc在glibc中,后者现在 都是共享库了吧

那么进入mallic后, malloc要为每个进程管理内存, 必须访问每个进程的内存管理状态数据, malloc如何知道是哪个进程在调用它呢?是不是要进内核获取当前进程 pid?

论坛徽章:
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
10 [报告]
发表于 2014-05-08 08:57 |只看该作者
不会,glibc 查询后,会存到进程空间的管理变量中。以后除非堆不够用,不然不会再次调用brk去扩堆。


malloc如何知道是哪个进程在调用它呢?是不是要进内核获取当前进程 pid?

malloc不需要知道他的PID是多少,是那个进程序调用它的?因为so的数据段是不同享的,每一个用到这个so的程序,都会在自身的程序空间存在一份独立的拷贝(虚拟进址和物理地址都不一样)。malloc只需要访问他的变量好的。
进程1放访问到的是进程1的变量2, 进程2放问到的是进程2的变量1, 不需要malloc去区分他是谁。

论坛徽章:
10
戌狗
日期:2013-10-17 09:43:0215-16赛季CBA联赛之广东
日期:2018-02-05 11:22:1215-16赛季CBA联赛之八一
日期:2016-07-04 12:26:1815-16赛季CBA联赛之青岛
日期:2016-06-08 11:15:4115-16赛季CBA联赛之辽宁
日期:2016-04-05 10:10:1415-16赛季CBA联赛之辽宁
日期:2016-03-11 11:11:48酉鸡
日期:2014-12-18 14:35:48狮子座
日期:2014-02-20 10:14:07寅虎
日期:2013-12-02 13:48:2915-16赛季CBA联赛之广夏
日期:2018-03-21 08:51:10
9 [报告]
发表于 2014-05-07 10:17 |只看该作者
貌似楼主的问题是会不会每次产生系统调用?

论坛徽章:
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
8 [报告]
发表于 2014-05-07 08:38 |只看该作者
回复 7# mordorwww

这个分析很简单:
1. 实践派:写个程序,strace一下就行。调了什么系统调用,返回值得是多少,一清二楚。
2. 理论分析派:man 一下sbrk手册,写得很清楚,在Linux下,brk和sbrk库调用,都是使用brk系统调用的。


在linux系统调用中。如果传0,就代表返回当前堆顶(第一次调用时和堆底同值,可以由strace结果进行验证)。

以下的代码摘自2.6.34.10内核mm/mmap.c文件。

  1. SYSCALL_DEFINE1(brk, unsigned long, brk)
  2. {
  3.         //<...>
  4.         unsigned long min_brk;
  5.         //<...>
  6. #ifdef CONFIG_COMPAT_BRK
  7.         min_brk = mm->end_code;
  8. #else
  9.         min_brk = mm->start_brk;
  10. #endif
  11.         if (brk < min_brk)
  12.                 goto out;

  13.         //<...>
  14. out:
  15.         retval = mm->brk;  //<--- 这就是内核管理的进程的栈顶!
  16.         //<...>
  17.         return retval;
  18. }
复制代码

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-13 06:20:00数据库技术版块每日发帖之星
日期:2016-06-15 06:20:00数据库技术版块每日发帖之星
日期:2016-06-16 06:20:00数据库技术版块每日发帖之星
日期:2016-06-18 06:20:00程序设计版块每日发帖之星
日期:2016-06-27 06:20:00程序设计版块每日发帖之星
日期:2016-07-09 06:20:00IT运维版块每日发帖之星
日期:2016-07-15 06:20:00IT运维版块每日发帖之星
日期:2016-07-27 06:20:00程序设计版块每日发帖之星
日期:2016-08-18 06:20:00
7 [报告]
发表于 2014-05-06 21:45 来自手机 |只看该作者
本帖最后由 mordorwww 于 2014-05-06 21:50 编辑

所以我问你malloc查询进程堆边界调用sbrk要不要进内核

论坛徽章:
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
6 [报告]
发表于 2014-05-06 21:01 |只看该作者
回复 5# mordorwww

通过sbrk(0)可以得到当前的堆顶。
整个程序刚才始运行时sbrk(0)得到的就是堆底。
运行过程中当可以通过sbrk(相对增加值)或brk(绝对地址)去扩展堆。
参见:http://linux.die.net/man/2/brk

堆由glibc的malloc方案去管理。
malloc的原理可以到百度文库搜索,有很多现成的分析。下面就是其中一编:
http://wenku.baidu.com/view/c7aebc05bed5b9f3f90f1cbc.html


   

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-13 06:20:00数据库技术版块每日发帖之星
日期:2016-06-15 06:20:00数据库技术版块每日发帖之星
日期:2016-06-16 06:20:00数据库技术版块每日发帖之星
日期:2016-06-18 06:20:00程序设计版块每日发帖之星
日期:2016-06-27 06:20:00程序设计版块每日发帖之星
日期:2016-07-09 06:20:00IT运维版块每日发帖之星
日期:2016-07-15 06:20:00IT运维版块每日发帖之星
日期:2016-07-27 06:20:00程序设计版块每日发帖之星
日期:2016-08-18 06:20:00
5 [报告]
发表于 2014-05-06 18:56 来自手机 |只看该作者
举例,每个进程的堆的边界在哪里,malloc如何知道

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
4 [报告]
发表于 2014-05-06 12:50 |只看该作者
完全同意2楼

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
3 [报告]
发表于 2014-05-06 08:00 |只看该作者
记得当前实习面试的时候被问到这个问题,当时想应该是用户态自己做了内存管理算法

楼上讲的很清楚

学习

论坛徽章:
0
2 [报告]
发表于 2014-05-06 00:39 |只看该作者
本帖最后由 l4rmbr 于 2014-05-06 00:45 编辑

回复 1# mordorwww


不会。malloc是属于C库层次的函数,是对系统调用的封装。它是实现在glibc中的一个库函数。

Glibc有自己的堆管理算法。它会一次性向OS"批发"比较大量的内存,然后以自己的堆管理算法来维护这部分内存,
以响应用户通过malloc等接口进行分配,但库存不足时,会再向OS“补仓”。
感兴趣者可以自行搜索相关信息。

Glibc的“批发”和”补仓“其实就是通过mmap, brk等系统调用, 在进程地址空间生成一个anonymous private映射,
在必要时通过brk调用进行扩容或减容。  

Glibc是共享库没错。但“共享”的意思是只有一份拷贝在内存中,但每个使用它的进程都会把其映射到自己的进程空间。
因此对于malloc的使用其实是per-process的。
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP