操作系统:malloc与堆区内存管理

malloc是函数而不是系统调用,他的底层是同调调用brk和mmap这两个系统调用实现功能的,具体选择brk还是mmap要看申请的空间大小以及malloc中的阈值(一般是128kb)

注意申请的空间只有使用才会触发缺页中断映射到物理内存

不理解的话先去学习一下分页和分段这些概念

brk

特点

  • 进行堆指针的偏移
  • 申请的空间会比申请的大
  • 容易产生内存碎片
  • 空间释放后不会返回给操作系统而是给内存池
  • 维持了内存池从而减少了系统调用

mmap

特点

  • 申请的空间大
  • 申请的空间释放后回归操作系统而非内存池
  • 从文件映射区挖一块内存

brk相较于mmap适合用作小空间处理的原因可以从两方面理解

  • brk的原理是移动堆指针,地址连续用着用着会产生大量的内存碎片,性能提升不会太高
  • 减少对操作系统并发性的影响,大空间被挖走当内存池会影响操作系统的整体性能

free释放时是如何知道释放多大空间的

在malloc的前边几个字段会存储申请的空间大小,释放的时候会偏移回去,可以借助指针看看,空间大小一般会比申请的大

cpp 复制代码
#include<iostream>
#include<stdlib.h>
using namespace std;
int main(){
    int *cur=(int*)malloc(32);
    for(int i=0;i<8;i++) cur[i]=i;
    for(int i=-5;i<15;i++){
        cout<<*(cur+i)<<endl;
    }
}

可以看到这里的实际大小是奇数,计算一下,堆的对齐方式是16字节,头部8字节,多申请一位应该是为了避免你申请8字节时出现堆指针和内存重叠的情况,你细品

内存不够用时申请物理内存会发生什么

如果没有空闲的物理内存,那么内核就会开始进行回收内存的工作,回收的方式主要是两种:直接内存回收和后台内存回收。

  • 后台内存回收:在物理内存紧张的时候,会唤醒 kswapd 内核线程来回收内存,这个回收内存的过程异步的,不会阻塞进程的执行。
  • 直接内存回收:如果后台异步回收跟不上进程内存申请的速度,就会开始直接回收,这个回收内存的过程是同步的,会阻塞进程的执行。
  • 如果直接内存回收后,空闲的物理内存仍然无法满足此次物理内存的申请,那么内核就会触发 OOM机制,OOM机制会根据页面置换算法选择一个占用物理内存较高的进程,然后将其杀死,以便释放内存资源,如果物理内存依然不足,OOM会继续杀死占用物理内存较高的进程,直到释放足够的内存位置。

回收对象

  • 文件页,缓存磁盘数据/缓存文件数据等,如果修改过没有提交是脏页需要进行页面置换,否则的话一般认为可以直接释放
  • 匿名页,比如栈、堆数据,这类必须要进行页面置换

所以说当申请的空间大于实际拥有的内存量时需要进行大量的文件IO会变得非常的卡,可以设置回收倾向来适当缓解,一般推荐优先回收文件页

new/delete和malloc/free的关系

相关推荐
添砖java‘’9 小时前
常见的进程间通信方式详解
linux·c++·操作系统·信息与通信·进程通信
西西弗Sisyphus12 小时前
C++ 实现支持 32 位和 64 位进程的模块枚举
开发语言·c++·操作系统
悄悄敲敲敲2 天前
操作系统的运行-中断
linux·操作系统
江湖人称贺行风2 天前
操作系统八股
操作系统·八股
Trouvaille ~2 天前
【Linux】进程调度与环境变量:Linux内核的智慧
linux·运维·服务器·操作系统·进程·环境变量·调度算法
肆忆_2 天前
Day5:线程池进阶——我从「只会跑 void 任务」到「能返回 future」,并用 Demo 验证跑通
操作系统
CS创新实验室2 天前
计算机考研408【操作系统】核心知识点总结
java·linux·考研·计算机·操作系统·408
_Voosk2 天前
C指针存储字符串为何不能修改内容
c语言·开发语言·汇编·c++·蓝桥杯·操作系统
OpenAnolis小助手3 天前
构建新计算范式下的开源生态,龙蜥技术生态分论坛回顾来了
开源·操作系统·龙蜥社区·openanolis
OpenAnolis小助手3 天前
专访 | 深耕八载,双向赋能:阿里云与龙蜥的开源共生之路
开源·云计算·操作系统·龙蜥社区·openanolis