是否malloc每次调用都会进入内核?
本帖最后由 mordorwww 于 2014-05-05 21:44 编辑malloc在glibc中,后者现在 都是共享库了吧
那么进入mallic后, malloc要为每个进程管理内存, 必须访问每个进程的内存管理状态数据, malloc如何知道是哪个进程在调用它呢?是不是要进内核获取当前进程 pid? 本帖最后由 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的。
记得当前实习面试的时候被问到这个问题,当时想应该是用户态自己做了内存管理算法
楼上讲的很清楚
学习 完全同意2楼 举例,每个进程的堆的边界在哪里,malloc如何知道 回复 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
本帖最后由 mordorwww 于 2014-05-06 21:50 编辑
所以我问你malloc查询进程堆边界调用sbrk要不要进内核 回复 7# mordorwww
这个分析很简单:
1. 实践派:写个程序,strace一下就行。调了什么系统调用,返回值得是多少,一清二楚。
2. 理论分析派:man 一下sbrk手册,写得很清楚,在Linux下,brk和sbrk库调用,都是使用brk系统调用的。
在linux系统调用中。如果传0,就代表返回当前堆顶(第一次调用时和堆底同值,可以由strace结果进行验证)。
以下的代码摘自2.6.34.10内核mm/mmap.c文件。
SYSCALL_DEFINE1(brk, unsigned long, brk)
{
//<...>
unsigned long min_brk;
//<...>
#ifdef CONFIG_COMPAT_BRK
min_brk = mm->end_code;
#else
min_brk = mm->start_brk;
#endif
if (brk < min_brk)
goto out;
//<...>
out:
retval = mm->brk;//<--- 这就是内核管理的进程的栈顶!
//<...>
return retval;
} 貌似楼主的问题是会不会每次产生系统调用? 不会,glibc 查询后,会存到进程空间的管理变量中。以后除非堆不够用,不然不会再次调用brk去扩堆。
malloc如何知道是哪个进程在调用它呢?是不是要进内核获取当前进程 pid?
malloc不需要知道他的PID是多少,是那个进程序调用它的?因为so的数据段是不同享的,每一个用到这个so的程序,都会在自身的程序空间存在一份独立的拷贝(虚拟进址和物理地址都不一样)。malloc只需要访问他的变量好的。
进程1放访问到的是进程1的变量2, 进程2放问到的是进程2的变量1, 不需要malloc去区分他是谁。
页:
[1]