Linux内存分配原理

news2024/11/17 16:49:20

Linux内存分配原理

  • 虚拟内存分区
    • Linux内存分配时的maps文件
  • brk()与sbrk()
  • mmap()与munmap()
    • mmap()
    • munmap()
  • 内存分配过程

请添加图片描述
更多资讯、知识,微信公众号搜索:“上官宏竹”。


虚拟内存分区

虚拟内存由于用途不同,分类也不尽相同,一般我们对于内存的分类也就这几种:栈区(stack area)、堆区(heap area)、全局区(静态区)(存放全局变量与静态变量static)、BSS段(存放未初始化的全局变量,未初始化的全局变量默认值为0)、文字常量区、数据区(data area)、代码区(code area)等。
在这里插入图片描述
栈区
栈区的内存空间由系统管理 --> 即方法调用开始时开辟空间,方法调用结束时回收空间。
栈区是从高地址向低地址扩展,是一块连续的内存区域,遵循先进后出,后进先出(FILO)原则,使用效率高。
栈区的内存空间是在运行时由系统进行分配。
哪些变量是栈区的?例如方法的入参,内部定义的局部变量等,都存放在栈区。
堆区
最大的特点 --> 空间大,需程序员自己手动管理。(当然,在ARC时代也是系统自动管理的)
堆区是从低地址向高地址扩展,与栈区相反,遵循先进先出(FIFO)的原则。
堆区由系统api开辟空间(c/c++ --> malloc、calloc、realloc, oc --> alloc new),这个空间可以是不连续的,以链表结构存在,
开辟出的空间的首地址是在栈区,例如LGPerson *person = [[LGPerson alloc] init];这个person指向所指向的地址是在栈区。
内存回收 --> free回收,做了两件事,一是释放堆区的内存,二是将栈区的指针置为nil。
全局静态区
存放全局变量 和 静态变量。
内存空间也是由系统管理 -->程序启动时开辟,程序结束时回收,程序执行期间一直存在。
static修饰的变量仅执行一次,生命周期为整个程序运行期。
常量区
存放常量(整型、字符型,浮点型,字符串等),整个程序运行期不能被改变。
已初始化的全局变量
已初始化的静态变量
空间由系统管理,生命周期为整个程序运行期。
代码区
存放程序执行的CPU指令,一种二进制文件。(编译期将代码转换为CPU指令)

Linux内存分配时的maps文件

# include<stdio.h>
# include<stdlib.h>
int num1;/*BSS段*/
int num2 = 2;/*全局区*/
char * str1 = "str1";/*文字常量区*/
int main(void){
    printf("%d\n",getpid());/*获取当前进程id号*/

    int num3 = 3;/*栈区*/
    static int num4 = 4;/*全局区*/
    const int num5 = 5;/*栈区*/
    char * str2 = "str2";/*文字常量区*/
    char str3[] = "str3";/*栈区*/
    int * p = malloc(sizeof(0));/*&p在栈区,p在堆区*/

    printf("num1:%p\nnum2:%p\nnum3:%p\nnum4:%p\nnum5:%p\n",&num1,&num2,&num3,&num4,&num5);
    printf("str1:%p\nstr2:%p\nstr3:%p\n",str1,str2,str3);
    printf("&p:%p\np:%p\n",&p,p);

    while(1){}/*死循环以保证进程不会结束,方便查看/proc/pid/maps文件*/

    free(p);

    return 0;
}

参考:内存管理与分页机制

brk()与sbrk()

参考:系统调用与内存管理(sbrk、brk、mmap、munmap)

mmap()与munmap()

mmap()

//函数原型:
#incldue<sys/mman.h>
void * mmap(void * addr, size_t length,int prot,int flags,int fd,off_t offset);

mmap函数(地址映射):mmap将一个文件或者其它对象映射进内存。
文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零(Linux堆空间未使用内存均清零)。这里我们只研究mmap的内存映射,而暂时不讨论文件方面的问题。
mmap内存地址映射区域是在堆、栈之间的区域,如下图所示的文件映射部分。
请添加图片描述

  • 参数
    (1)、addr:
    起始地址,置零让系统自行选择并返回即可。
    (2)、length:
    长度,不够一页会自动凑够一页的整数倍,我们可以宏定义#define MIN_LENGTH_MMAP 4096为一页大小。
    (3)、prot:
    读写操作权限,PROT_READ可读、PROT_WRITE可写、PROT_EXEC可执行、PROT_NONE映射区域不能读取。(注意PROT_XXXXX与文件本身的权限不冲突,如果在程序中不设定任何权限,即使本身存在读写权限,该进程也不能对其操作)。
    (4)、flags常用标志:
    ① MAP_SHARED【share this mapping】、MAP_PRIVATE【Create a private copy-on-write mapping】
    MAP_SHARED只能设置文件共享,不能地址共享,即使设置了共享,对于两个进程来说,也不会生效。而MAP_PRIVATE则对于文件与内存都可以设置为私有。
    ② MAP_ANON【Deprecated】、MAP_ANONYMOUS:匿名映射,如果映射地址需要加该参数,如果不加默认映射文件。MAP_ANON已经过时,只需使用MAP_ANONYMOUS即可。
    (5)、fd:文件描述符。
    (6)、offset:文件描述符偏移量
    (fd和offset对于一般性内存分配来说设置为0即可)
  • 返回值
    失败返回MAP_FAILED,即(void * (-1))并设置errno全局变量。
    成功返回指向mmap area的指针pointer。
  • 常见errno错误
    ①ENOMEM:内存不足;
    ②EAGAIN:文件被锁住或有太多内存被锁住;
    ③EBADF:参数fd不是有效的文件描述符;
    ④EACCES:存在权限错误,。如果是MAP_PRIVATE情况下文件必须可读;使用MAP_SHARED则文件必须能写入,且设置prot权限必须为PROT_WRITE。
    ⑤EINVAL:参数addr、length或者offset中有不合法参数存在。

munmap()

munmap函数:解除映射关系

// addr为mmap函数返回接收的地址,length为请求分配的长度。
int munmap(void * addr, size_t length);

内存分配过程

从操作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。brk是将数据段(.data)的最高地址指针_edata往高地址推,mmap是在进程的虚拟地址空间中(一般是堆和栈中间)找一块空闲的。
这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。
在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk,mmap,munmap这些系统调用实现的。
下面以一个例子来说明内存分配的原理:
在这里插入图片描述
1 进程启动的时候,其虚拟内存空间的初始布局如图1所示。其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。_edata指针(glibc里面定义)指向数据段的最高地址。
2 进程调用A=malloc(30K)以后,内存空间如图2:malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配。你可能会问:只要把_edata+30K就完成内存分配了?事实是这样的,_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。
3进程调用B=malloc(40K)以后,内存空间如图3.
在这里插入图片描述
4 进程调用C=malloc(200K)以后,内存空间如图4:默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。这样子做主要是因为brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的),而mmap分配的内存可以单独释放。当然,还有其它的好处,也有坏处,再具体下去,有兴趣的同学可以去看glibc里面malloc的代码了。
5 进程调用D=malloc(100K)以后,内存空间如图5.
6 进程调用free©以后,C对应的虚拟内存和物理内存一起释放
在这里插入图片描述
7 进程调用free(B)以后,如图7所示。B对应的虚拟内存和物理内存都没有释放,因为只有一个_edata指针,如果往回推,那么D这块内存怎么办呢?当然,B这块内存,是可以重用的,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去了。
8 进程调用free(D)以后,如图8所示。B和D连接起来,变成一块140K的空闲内存。
9 默认情况下:当最高地址空间的空闲内存超过128K(可由M_TRIM_THRESHOLD选项调节)时,执行内存紧缩操作(trim)。在上一个步骤free的时候,发现最高地址空闲内存超过128K,于是内存紧缩,变成图9所示。


更多资讯、知识,微信公众号搜索:“上官宏竹”。
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

底层网络知识详解:从二层到三层-第6讲-交换机与VLAN:办公室太复杂,我要回学校

上一次,我们在宿舍里组建了一个本地的局域网LAN,可以愉快地玩游戏了。这是一个非常简单的场景,因为只有一台交换机,电脑数目很少。今天,让我们切换到一个稍微复杂一点的场景,办公室。 拓扑结构是怎么形成的? 我们常见到的办公室大多是一排排的桌子,每个桌子都有网口,…

C++11标准模板(STL)- 算法(std::minmax_element)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 返回范围内的最小元素和最…

非零基础自学Golang 第11章 文件操作 11.2 文件基本操作 11.2.1 文件创建与打开

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.2 文件基本操作11.2.1 文件创建与打开第11章 文件操作 11.2 文件基本操作 在学习文件操作之前&#xff0c;我们先来了解一下Linux下的文件权限。 文件有三种权限&#xff0c;分别为读取、写入和执行&#x…

设计模式2 - 创建型模式

23种设计模式分析与见解开篇、UML、软件设计原则https://blog.csdn.net/lili40342/article/details/128358435创建型模式https://blog.csdn.net/lili40342/article/details/128358392结构型模式https://blog.csdn.net/lili40342/article/details/128358313行为型模式https://bl…

【MATLAB100个实用小技巧】——图形处理(67-75)

文章目录前言系列文章67. 图像的块操作68. 图形的过滤操作69. 图像的频率操作70. 函数变换71. RADON 函数变换72. 图像分析&#xff08;1&#xff09;73. 过滤图像74. 图像的区域处理75. 图像的颜色处置前言 &#x1f30f;MATLAB是一个功能强大的软件&#xff0c;我们可以利用M…

Mycat(3):mycat的安装

1、前言 使用mycat要安装JDK.不会的去看Linux里面的安装JDK的知识点&#xff0c;这是不再做说明 也可以直接使用yum install java-1.7.0-openjdk 因为mycat 基于jdk1.7开发的&#xff0c;所有最好安装jdk1.7的版本 重要说明&#xff1a; Mycat-server-1.6-release 版本发布的版…

手机技巧:苹果手机这8个实用小技巧

今天给大家大家分享苹果手机8个实用小技巧&#xff0c;你都会用吗&#xff1f; 1、快速搜索相机照片 相信大家的相册里的照片应该和我一样不说有几千张&#xff0c;几百张总是有的&#xff0c;有时候想找照片&#xff0c;又不想一张一张找怎么办&#xff1f;很简单&#xff0c…

Docker配置从私有仓库拉取镜像

修改Docker配置文件 修改docker的配置文件daemon.json&#xff0c;如果配置文件不存在则直接创建。 vim /etc/docker/daemon.json文件内容如下&#xff0c;其中insecure-registries属性值“registry.luntek-inc.com”代表私有仓库的地址&#xff0c;你需要将registry.luntek-…

JavaSE13-方法

目录 1.方法的基本用法 1.1.什么是方法 1.2.方法定义语法 1.3.方法调用的执行过程 1.4.实参和形参的关系 1.5.方法的返回值 2.方法重载 2.1.方法重载定义 2.2.代码示例 3.方法递归 3.1.方法递归定义 3.2.方法递归使用条件 3.3.递归与非递归优劣比较 3.4.递归执行…

[附源码]Nodejs计算机毕业设计基于网络C++实验管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

SpringBoot+Vue项目部门人事管理系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

Vit 中的 Token 改进版本:Token Mreging: Your Vit But Faster 论文阅读笔记

Vit 中的 Token 改进版本&#xff1a;Token Mreging: Your Vit But Faster 论文阅读笔记一、Abstract二、引言三、相关工作3.1 有效的 Transformer3.2 Token 的减少3.3 Token 的联合四、Token 融合4.1 策略4.2 Token 相似性4.3 双边软匹配4.4 追踪 Token 的尺寸4.5 采用融合操作…

[附源码]计算机毕业设计Python餐馆点餐管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

非零基础自学Golang 第11章 文件操作 11.3 处理JSON文件 11.3.2 解码JSON 11.4 小结

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.3 处理JSON文件11.3.2 解码JSON11.4 小结第11章 文件操作 11.3 处理JSON文件 11.3.2 解码JSON 解码JSON会使用到Unmarshal接口&#xff0c;也就是Marshal的反操作。 func Unmarshal(data []byte, v interf…

30岁零基础没学历学Python怎么样?30岁学习Python晚吗?

30岁零基础没学历学Python怎么样&#xff1f;30岁学习Python晚吗&#xff1f;任何时候开始都不晚。30岁开始学习Python听起来年纪有点大&#xff0c;大家认为编程上了年纪学习编程语言是一个劣势。想在三十岁的时候通过学习Python来谋求一份IT程序员工作&#xff0c;则需要有一…

SQL笔记

SQL笔记 基本概述 数据库&#xff1a;保存有组织的数据的容器&#xff08;通常是一个文件或一组文件&#xff09;。容易混淆&#xff1a;人们通常用数据库这个术语来代表他们使用的数据库软件&#xff0c;这是不正确的&#xff0c;也因此产生了许多混淆。确切地说&#xff0c…

抖音关键词排名优化技巧,手把手教你怎样优化抖音关键词

云南百收科技有限公司 1、标题中出现关键词是关键词排名靠前的基础。 一篇文章中标题中一定要出现你想做的关键词&#xff0c;因为搜索引擎是是匹配标题的&#xff0c;如果你标题中没有关键词&#xff0c;是不会有排名的。而且还有一点&#xff0c;关键词的位置要靠近标题最前面…

python+pyqt5+mysql设计图书管理系统(1)- 数据库

一、概述 前面学习了python,pyqt和mysql的一些基础知识,接下来运用学习的东西进行实操制作一个项目--图书管理系统。 项目介绍:图书管理系统对于我们的图书管理来说非常重要,管理图书者可以通过系统有效的管理书籍,用户可以通过系统快速有效的找到自己需要的书籍。相比人工…

【目标跟踪】Kalman滤波目标跟踪【含Matlab源码 388期】

⛄一、获取代码方式 获取代码方式1&#xff1a; 通过订阅紫极神光博客付费专栏&#xff0c;凭支付凭证&#xff0c;私信博主&#xff0c;可获得此代码。 获取代码方式2&#xff1a; 完整代码已上传我的资源&#xff1a;【目标跟踪】基于matlab Kalman滤波目标跟踪【含Matlab源…

聊一聊Unity的Test Framework应该怎么用

其实 Unity 很早就出了这个包&#xff0c;不过感觉基本上没什么人用&#xff0c;这么好的东西&#xff0c;本着让所有人都能了解的态度&#xff0c;今天就来聊聊它应该怎么使用。 第1步先安装它&#xff0c;或者给它升级到最新。 第2步打开工具的主窗口 支持分别在 PlayMode 或…