malloc实现原理
malloc是什么?
通过malloc,我们可以开辟一个自定义大小的内存空间。
通过上图我们可以知道,malloc是一个C的库函数,参数是分配一个size大小(正整数)的空间,分配成功后返回一个void*
指针,说明可以通过强转,返回一个任意类型的指针。分配空间失败后返回null
。
malloc,calloc, realloc的区别
根据上图来说明:
- malloc: 分配size字节大小的空间,分配空间成功后返回一个
void*
指针;分配空间失败后返回null
。 - calloc: 分配num个size字节大小的空间,分配空间成功后返回一个
void*
指针;分配空间失败后返回null
。 - realloc: 对ptr指针指向的空间,将其大小改变为size字节大小。成功后返回一个
void*
指针;失败后返回null
。具体可以参考博客:realloc的用法。
malloc的实现原理
malloc是C库函数,所以底层肯定使用系统调用来实现。
malloc分配内存的时候,会预分配一个更大的空间作为内存池,然后在内存池上面划分所申请大小的空间并返回,free时也不会将空间直接释放,而是将空间归还给内存池。但通过后面我们可以知道,只有当底层使用brk时才是这样的,使用mmap时直接分配内存,free后就还给OS,不会和内存池产生交互。
malloc的两种实现方式
malloc通过以下两个系统调用来实现:
- brk: 当分配的空间大小 小于 128KB时, 在堆上分配空间。
- mmap: 当分配的空间大小 大于 128KB时, 在文件映射区上分配空间。
为什么使用brk?
当分配的空间大小 小于 128KB时, 在堆上分配空间。为什么这样设计呢?
因为mmap使用完内存free会直接释放归还给操作系统,频繁的调用mmap会使得用户态和内核态来回切换,会降低效率,于是利用了内存池来解决这个问题,每次调用brk函数都会预分配更大的空间来放入内存池,下一次在调用brk的时候,就可以不用切换为内核态,直接将内存池的空间分配即可,提高了效率。
为什么使用mmap?
为什么使用mmap呢?
因为brk在内存池中的释放空间和申请空间都会造成许多内存碎片,如果我们频繁申请很多大空间的内存,如果都使用brk,就会造成内存池中出现许多空间大的内存碎片,造成了空间浪费。
所以,当我们申请小空间的内存时,使用brk,将其放入内存池,就算形成内存碎片也不会造成很大的空间浪费, 而且减少了内核态和用户态的切换,提高了效率。当我们申请大空间的内存时,使用mmap,就能避免内存池中没有合适大小的空间,并且free后直接释放给了操作系统,避免了造成更大的空间浪费。
malloc怎么定界的
malloc分配空间时,会返回一个指向所申请空间开头地址的指针,那么只靠这一个指针,是怎么分辨分配空间的界限的呢?怎么知道空间有多大呢?
原因是因为malloc在分配内存时,多分配了一段内存空间,其中存储了用户所需空间的大小,有了这个我们就能确定界限。这段多分配的空间就在malloc返回的指针指向地址的前面的空间处。如图:
malloc分配的是虚拟内存上的空间吗?
malloc分配的是虚拟内存上的空间,一开始并不会在物理内存上面分配内存,当我们使用这个空间的时候,拿到这个虚拟地址,去页表查询,会发现没有对应的页表项,就会触发缺页中断,然后操作系统在物理内存分配相应大小的空间,更新页表,再重新查询,这时候,才会真正的在物理内存上分配内存。
所以,如果一直使用mmap,每次都释放空间给操作系统,页表中的页表项也会被删除,再进行申请空间的, 使用空间的时候,就会造成缺页中断,造成效率低下。而使用brk不会将内存空间返还给操作系统,页表中这个已经free的空间和物理内存页面的映射关系可能还在,下次申请空间时就不会造成缺页中断。
标签:malloc,mmap,brk,Liunx,空间,原理,分配,内存 From: https://blog.csdn.net/tang20030306/article/details/140316028新人创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看。