1、虚拟内存、物理内存和页表
![b3b69684b88fe33f5fbf403992169739.png](https://i-blog.csdnimg.cn/blog_migrate/18bdd22f350b1a0d08b638b697eeefde.jpeg)
每一个进程都有自身的虚拟内存,通过页表将虚拟内存映射到物理内存。虚拟内存空间被内核划分为了等长的部分,这部分称之为页,物理内存也被划分为了同样大小的页,通常称之为页帧。
![fa6281983b5c2cd335bf06ecf7227354.png](https://i-blog.csdnimg.cn/blog_migrate/63220b8be3922b8d44fb8f28064bd1c6.png)
不同的虚拟内存空间中的页可以映射到同一个物理内存页,内核可以决定哪些内存区域在进程间共享,哪些不共享;不是所有的虚拟空间页都会映射到物理内存,虚拟空间远大于物理内存。
用来将虚拟地址空间映射到物理地址空间的数据结构称为页表,实际中为了提高性能、节省空间往往采用多级页表,linux 采用了四级页表。
虚拟内存中的栈主要保存函数的参数、返回值和局部变量等,由编译器管理;用户主动申请的内存主要保存在堆中,由用户和编译器共同管理,并且堆中内存需要垃圾回收机制,java、go、python等语言本身会负责垃圾回收,c、c++等需要用户自己负责内存的申请和释放。
2、简单的内存分配方法
- 线性分配
维护一个指向内存的指针,移动指针实现内存的分配
![46e3b95553277378b9e6736f368fabf1.png](https://i-blog.csdnimg.cn/blog_migrate/1c03ddb2114318f40c3c4f1e0885d1f2.png)
实现复杂度低,内存分配快,但需要不停拷贝、合并内存以实现内存释放和回收
- 链表分配器
维护一个空闲内存的链表
![d1c13448e24404e6910218048b9fbd64.png](https://i-blog.csdnimg.cn/blog_migrate/835f65c418bd54f05755343eabc6e8e9.png)
实现复杂度低,内存的释放和回收简单,但是需要遍历链表,为了进一步提高效率,可以把内存分割成不同的大小,分别组成不同的链表,根据申请内存的大小使用相应的链表
3、TCMalloc
线程缓存分配(TCMalloc,thread-caching malloc)是一种快