内存分配机制的发展过程:

第一阶段——程序直接操作物理内存。

某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存100。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出100M分配给程序B

1.进程地址空间不隔离。

进程之间可以互相修改内存,导致不安全,可能会出现一个进程出现bug,导致另一个本来好好的进程挂掉。

2.内存使用效率低。

在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要30M大小的内存才能运行,而此时系统只剩下18M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序C使用,然后再将程序C的数据全部装入内存中运行。

3.程序运行的地址不确定。

当内存中的剩余空间可以满足程序C的要求后,操作系统会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的。

虚拟内存
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。

第二阶段——分段(解决了第一阶段的第1和第3个问题)

在进程和物理内存增加一个中间层,利用一种间接的地址访问方法访问物理内存。程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。

第三阶段——分页(解决了第一阶段的第2个问题)

将地址空间分成许多的页。每页的大小由CPU决定,然后由操作系统选择页的大小。目前Inter系列的CPU支持4KB或4MB的页大小,而PC上目前都选择使用4KB。

对比分段

在分段的方法中,每次程序运行时总是把程序全部装入内存,而分页的方法则有所不同。分页的思想是程序运行时用到哪页就为哪页分配内存,没用到的页暂时保留在硬盘上。当用到这些页时再在物理地址空间中为这些页分配内存,然后建立虚拟地址空间中的页和刚分配的物理内存页间的映射。

举例说明加载可执行文件的过程
一个可执行文件(PE文件)其实就是一些编译链接好的数据和指令的集合,它也会被分成很多页,在PE文件执行的过程中,它往内存中装载的单位就是页。当一个PE文件被执行时,操作系统会先为该程序创建一个4GB的进程虚拟地址空间。前面介绍过,虚拟地址空间只是一个中间层而已,它的功能是利用一种映射机制将虚拟地址空间映射到物理地址空间,所以,创建4GB虚拟地址空间其实并不是要真的创建空间,只是要创建那种映射机制所需要的数据结构而已,这种数据结构就是页目和页表。

.当创建完虚拟地址空间所需要的数据结构后,进程开始读取PE文件的第一页。在PE文件的第一页包含了PE文件头和段表等信息,进程根据文件头和段表等信息,将PE文件中所有的段一一映射到虚拟地址空间中相应的页(PE文件中的段的长度都是页长的整数倍)。这时PE文件的真正指令和数据还没有被装入内存中,操作系统只是根据PE文件的头部等信息建立了PE文件和进程虚拟地址空间中页的映射关系而已。当CPU要访问程序中用到的某个虚拟地址时,当CPU发现该地址并没有相相关联的物理地址时,CPU认为该虚拟地址所在的页面是个空页面,CPU会认为这是个页错误(Page Fault),CPU也就知道了操作系统还未给该PE页面分配内存,CPU会将控制权交还给操作系统。操作系统于是为该PE页面在物理空间中分配一个页面,然后再将这个物理页面与虚拟空间中的虚拟页面映射起来,然后将控制权再还给进程,进程从刚才发生页错误的位置重新开始执行。由于此时已为PE文件的那个页面分配了内存,所以就不会发生页错误了。随着程序的执行,页错误会不断地产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求。

分页方法的核心思想就是当可执行文件执行到第x页时,就为第x页分配一个内存页y,然后再将这个内存页添加到进程虚拟地址空间的映射表中,这个映射表就相当于一个y=f(x)函数。应用程序通过这个映射表就可以访问到x页关联的y页了。

内存管理

最小存储单位是一个字节(1B),最小管理单位是一页(4KB),虚拟内存地址连续时物理内存地址可以不连续,即使一次分配6000字节(不到两页也分配两页),两个内存页物理地址可能不连续。多次申请内存时,如果之前分配的页内存没用完,则不再分配,除非之前分配的内存页用完才继续映射新的一页。硬盘也是如此(硬盘上称为Block块)。

例如test文件里面只有4个字符,却也需要占4K的大小。

C语言中的malloc函数

#include<stdio.h>
#include<stdlib.h>
int main(void){char * p = malloc(0);printf("%d,%d\n",*(p),*(p+32*4096));//打印第33页的内容,被默认初始化。free(p);
}

运行结果如下:

#include<stdio.h>
#include<stdlib.h>
int main(void){char * p = malloc(0);printf("%d,%d\n",*(p),*(p+33*4096));//打印第4页的内存位置,报段错误free(p);
}

运行结果如下:段错误是因为超过的虚拟内存地址并没有映射(分配)物理内存。

free函数

malloc()给变量分配给变量内存时,除了数据区域外,还额外需要保存一些信息。底层有一个双向链表保存额外信息。malloc()给指针了12个字节,其中4个字节存放数据,另外8个存放其他信息或者空闲,如果将12个字节中前(低位)几个字节清空或者进行修改,free就可能出错,因为free只有首地址不能释放,还得需要额外附加信息(如malloc分配的长度)

修改malloc申请的内存的指针位置,free会无法正常释放内存。

上图中的:

此处又再次证明了malloc每一次分配的的内存页是33页。

修改malloc申请的内存的指针的前几位的值,free也会无法正常释放内存。

参考文章https://blog.csdn.net/ljabclj/article/details/44155221

C语言——操作系统内存分配过程相关推荐

  1. java 线程 内存分配内存_漫谈JAVA语言的内存分配

    在说JAVA语言的内存分配之前,我们先聊聊OS的Memory Management,这是学习操作系统课程的一个重要内容.从这里开始理解内存分配有利于理解的更深入. 我们知道物理内存是由page 和se ...

  2. 独占设备的分配与回收_灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?...

    点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 作者 l Hollis JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆.栈. ...

  3. 原创 | 灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?

    △Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 222 篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) JVM内存结构,是很 ...

  4. C语言的内存分配模型

    C语言的内存分配模型 2008-03-12 19:32 C语言中的内存地址分配模型如下: 说明: 1.程序代码区:存放函数体的二进制代码. 2.全局区数据区:全局数据区划分为三个区域.全局变量和静态变 ...

  5. java内存分配空间大小,JVM内存模型及内存分配过程

    一.JVM内存模型 JVM主要管理两种类型内存:堆(Heap)和非堆(Permanent区域). 1.Heap是运行时数据区域,所有类实例和数组的内存均从此处分配.Heap区分两大块,一块是 Youn ...

  6. ART对象内存分配过程解析(上)——内存分配的准备阶段(Android 8.1)

    注:本文基于Android 8.1进行分析. ART对象分配过程解析--内存分配的准备阶段 本章我们将分析Android 8.1中ART虚拟机的对象创建时内存分配过程的分析.本节将介绍内存分配相关的环 ...

  7. 操作系统C语言模拟内存分配算法的模拟实现

    使用一个一维数组来模拟内存储空间,建立内存块来记录内存分配使用情况,通过随机产生进程及其所需要的内存来模拟真实的进程.通过给进程分配内存及回收来实现对动态不等长存储管理方法. 代码 #include ...

  8. linux 在指定区域分配内存 c语言,C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存...

    一.malloc/free概述 malloc是在C语言中用于在程序运行时在堆中进行动态内存分配的库函数.free是进行内存释放的库函数. 1.函数原型 #include void *malloc( s ...

  9. C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存

    最新个人博客 shankusu.me 以下内容转载或参考或引用自 https://blog.csdn.net/zxx910509/article/details/62881131 一.malloc/f ...

最新文章

  1. pythond的执行原理_python基础——继承实现的原理
  2. python——类和对象之__str__方法的使用
  3. 携程基于Quasar协程的NIO实践
  4. 3-6-汉诺塔(Hanoi Tower)问题-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版...
  5. SAP CDS view里将Date和time连接成timestamp的函数
  6. 20080408 - VS2003 中 Jscript 文件中文乱码问题
  7. python yield from_简述 yield 和 yield from
  8. EBS_FORM_开发:关于切换不同BLOCK的时候弹出需要保存的窗口
  9. 系统学习机器学习之神经网络(五) --ART
  10. python中面向对象的ui_Python面向对象和图形用户界面(一)---- 面向对象
  11. html设置表格边框样式
  12. 基于销售数据的决策支持系统的设计与实现源码论文
  13. 引用 八卦象数疗法--配方2
  14. java中sep_java时间格式转换: Sep 29, 2012 1:00:01 AM 怎么转换成标准的java Date对象
  15. 互联网日报 | 5月18日 星期二 | 中国移动启动A股上市;京东物流启动全球招股;快手发布首款自研手游产品...
  16. 浅析爱心代码的绘制思路——python实现
  17. 一个熟练程序员所具备的特质-2
  18. 华为nova5里面有用到鸿蒙吗,华为nova7se是不是鸿蒙系统?
  19. matlab 图象退化 motion,图象运动退化,image motion blurred,音标,读音,翻译,英文例句,英语词典...
  20. 练手:原生js(部分jquery)写一个前端页面分页功能

热门文章

  1. 记一次CLTPHP渗透测试
  2. 基于 HTML5 结合工业互联网的智能飞机控制
  3. TCP/IP五层协议及功能
  4. react移动端适配
  5. 如何在电脑上录音给视频配乐
  6. string的常用用法详解
  7. Canny算子的理解
  8. stm32 不停重启
  9. 阿里钉钉火了,疫情过后将超过腾讯微信?
  10. 网易内部邮箱coremail smtp pop设置