操作系统②——内存管理

1. 栈、堆

1.1 程序的内存分配

  • 栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
  • 全局区/静态区(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
  • 常量区:常量字符串就是放在这里的。 程序结束后由系统释放
  • 程序代码区:存放函数体的二进制代码
int a = 0;   // 全局初始化区
char *p1;   // 全局未初始化区
int main{int b;  // 栈char s[] = "abc"; // 栈char *p2;  // 栈char *p3 = "123456";  // 123456\0在常量区,p3在栈区static int c = 0;   // 全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);// 分配得来的10和20字节的区域在堆区strcpy(p1, "123456");  // 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方return 0;
}

1.2 申请方式

  • stack:由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
  • heap:需要程序员自己申请,在c中使用malloc,在c++中使用new
    • 注意:p1 = (char *)malloc(10); 这里的p1本身是在栈中的,分配的10个字节的区域在堆中

1.3 申请后系统的响应

  • 栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出
  • 堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
    会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

1.4 申请大小的限制

  • 栈:栈是向低地址扩展的数据结构,是一块连续的内存的区域,即栈顶的地址和栈的最大容量是系统预先规定好的,如果申请的空间超过栈的剩余空间时,将提示overflow。
    • 能从栈获得的空间较小
  • 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。
    • 堆获得的空间比较灵活,也比较大。

1.5 申请效率

  • 栈由系统自动分配,速度较快。但程序员是无法控制的。
  • 堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

1.6 堆和栈中的存储内容

  • 栈:在函数调用时,第一个进栈的是主函数的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
  • 堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

1.7 栈溢出的情况

  • 局部数组过大
  • 递归调用层次太多,压栈次数太多

2. 缓冲区溢出的危害

  • 缓冲区是指展示放置输入输出资料的内存
  • 缓冲区溢出是指向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖了合法数据
  • 危害:程序崩溃、跳转执行一段恶意代码

3. 分段和分页

  • 分段和分页的出现,是为了解决连续分配内存管理带来的问题而设计出的一种新管理内存的方案

3.1 分段

  • 一个进程不是完完整整的放入到连续的内存区域,而是把进程分段放入内存,因为把进程连续的放入内存带来的问题就是碎片问题很严重,所以分段放入内存就可以有效的缓解碎片问题;
  • 分段允许逻辑地址空间的进程放入内存是不连续的,也就是说在内存的进程不是连续排列的,而是七零八落散落各个位置;
  • 分段的基本思路:
    • 分段机制的逻辑地址位由<段号,段内位移>组成,为了让逻辑地址映射到物理地址,OS需要维护一张表,该表名字就是段表;
    • 段表里记录三个信息:1. 段号,2.段内基地址,3.段的大小
    • 当我们逻辑地址需要转为物理地址时候,需要先查找逻辑地址的段号,根据段号去段表查找该段的基地址,还有段的大小;再把段的基地址,和段的大小放入两个寄存器:base 和 limit 两个寄存器中;再拿到limit寄存器的值,也就是段的大小,和逻辑地址的段内位移比较;段内唯一比段的大小大,就是非法地址,段内唯一比短的大小小就是合法地址;
    • 合法地址就把段内位移加上base寄存器的值,也就是段内基地址,这样就找到了物理地址。

3.2 分页

  • 分段管理虽然减少了内存碎片,但是减少的还是不够多,多多少少还是会有内存碎片,为进一步减少内存碎片问题提出分页机制
  • 分页的基本思路:
    • 把内存分为固定大小的分区,程序也被切成固定大小分区;内存固定大小的分区叫页框,程序的固定大小分区称为页面;页框的大小是等于页面的大小的
    • 分页也会产生内存碎片,但是这个内存碎片式可控的;
    • 假设固定大小为4kb,而程序只有39kb的大小,那么分10个页面,只有第10个页面的大小为3kb,其他页面的大小都是4kb;当把程序的每个页面都放进内存的也框中,只有第10个页面是占页框的3kb,页框就会剩下1kb,这也是内部碎片的产生,但是这个内部碎片很小,说明我们控制的还是相当合理的;
    • 有了分页机制,我们的逻辑地址就可以表示为:页号+页内位移;逻辑地址转物理地址就可以通过逻辑地址的页号,找到对应的页框,然后页框号乘于页框大小加上页内位移就得到了物理地址;
    • OS内部是直接通过:把逻辑地址的页号,替换成页号对应的页框,然后就和页内位移直接组合成物理地址。

3.3 分段与分页的区别

  • 分段的是以信息逻辑单位划分内存空间,也就是每个程序的空间,是一个一个逻辑划分的,比如一个函数一个函数的逻辑单元;而分页就是固定大小的空间划分的;
  • 分段的段长是任意的;分页的页长由系统确定;
  • 分段中段的起始地址可以从主存任一地址开始;分页中页框起始地址只能以页框大小的整数倍开始
  • 分段会产生外部碎片;分页消除了外部碎片但会出现内部碎片

4. 页面置换算法(发⽣缺⻚异常时调换⻚⾯)

  • 页面置换算法主要用于解决进程运行过程中内存不足的问题。当进程需要访问的页面不在内存内,而内存又已满时,就需要通过页面置换算法选择一个页面进行替换,以腾出空间加载所需页面。
  • FIFO(先进先出)算法:
    • 每次选择最早进⼊内存的⻆⾊进⾏切换。
    • 这种策略很简单,只需要维护⼀个⻆⾊队列,每次淘汰队⾸的⻆⾊,然后把新的⻆⾊加⼊队尾。但是FIFO算法可能会淘汰⼀些经常被使⽤的⻆⾊,导致切换次数增加。
    • FIFO算法有可能出现⻉拉迪异常,即当分配给内存的空间增加时,切换次数反⽽增加。
  • LRU(最近最少使⽤)算法:
    • 每次选择最⻓时间没有被使⽤的⻆⾊进⾏切换。
    • 这种策略基于你对⻆⾊的喜好,认为最近被使⽤过的⻆⾊很可能还会被使⽤,⽽最久未被使⽤的⻆⾊很可能不会再被使⽤。
    • LRU算法可以有效地减少切换次数,但是实现起来⽐较复杂,需要记录每个⻆⾊的使⽤时间或者维护⼀个使⽤顺序的列表。
  • 最佳⻚⾯置换算法(OPT):
    • 置换在未来最⻓时间不访问的⻚⾯
    • 在实际系统中⽆法实现,因为程序访问⻚⾯时是动态的我们是⽆法预知每个⻚⾯在下⼀次访问前的等待时间,因此作为实际算法效率衡量标准
  • 时钟⻚⾯置换算法:
    • 把所有的⻚⾯都保存在⼀个类似钟⾯的环形链表中,⻚⾯包含⼀个访问位。当发⽣缺⻚中断时,顺时针遍历⻚⾯,如果访问位为1,将其改为0,继续遍历,直到访问到访问位为0⻚⾯,进⾏置换。
  • 最不常⽤算法 :
    • 记录每个⻚⾯访问次数,当发⽣缺⻚中断时候,将访问次数最少的⻚⾯置换出去
    • 此⽅法需要对每个⻚⾯访问次数统计,额外开销。

5. 动态分区分配算法

  • 所谓动态分区分配,就是指内存在初始时不会划分区域,而是会在进程装入时,根据所要装入的进程大小动态地对内存空间进行划分,以提高内存空间利用率,降低碎片的大小
  • 首次适应算法:
    • 空闲分区以地址递增的次序链接。分配内存时顺序查找,找到大小满足要求的第一个空闲分区就进行分配。

在这里插入图片描述

  • 临近适应算法:
    • 又称循环首次适应法,由首次适应法演变而成,不同之处是分配内存时从上一次查找结束的位置开始继续查找。

在这里插入图片描述

  • 最佳适应算法:
    • 空闲分区按容量递增形成分区链,找到第一个能满足要求的空闲分区就进行分配。(优先使用小的空闲区,这样会留下很多外部碎片)

在这里插入图片描述

  • 最坏适应算法:
    • 空闲分区以容量递减的次序链接,找到第一个能满足要求的空闲分区(也就是最大的分区)就进行分配

在这里插入图片描述

  • 算法对比

在这里插入图片描述

6. 虚拟内存

  • 虚拟内存使得应⽤程序认为拥有连续的可⽤的内存,实际上,是多个物理内存碎⽚
  • 虚拟内存使⽤部分加载的技术,让⼀个进程或者资源的某些⻚⾯加载进内存(不是全部加载),从⽽能够加载更多的进程,甚⾄能加载⽐内存⼤的进程
  • 优点:
    • 较⼩的可⽤内存中执⾏较⼤的用户程序
    • 在内存中容纳更多程序并发执⾏
    • 与覆盖技术相⽐,不会影响编程时的程序结构
  • 缺点:占用了一定的物理硬盘空间
  • 虚拟内存实现⽅式:请求分⻚存储管理、分段、段⻚式

7. 常见的内存分配错误

  • 内存没有分配成功,却使⽤了
  • 内存分配成功,但未初始化
  • 内存分配成功且初始化,但操作越界
  • 忘记释放内存,内存泄露
  • 释放内存依旧使⽤:释放后没有置为NULL,产⽣野指针

8. 内存交换中,被换出的进程保存在哪?

  • 保存在磁盘中,也就是外存中
  • 磁盘 = 文件区 + 对换区,进程存放在对换区
    • 文件区:存放⽂件、离散分配、追求空间利⽤率
    • 对换区:存放进程数据、连续分配、提⾼对换速度

9. 抖动/颠簸

  • 刚刚换出的⻚⾯⻢上换⼊内存,刚刚换⼊的⻚⾯⻢上换出外存,频繁的⻚⾯调度,就会出现抖动颠簸
  • 原因:进程频繁访问的⻚⾯数⽬⽐分配的物理块多
  • 抖动影响效率,虚拟内存管理器将⼀定量的内存⻚驻留在内存中,根据进程工作的指标,动态调整这个⻚⾯数量

10. 操作系统的局部性原理

  • 程序常常会使⽤集中在⼀起的局部数据
  • 时间局部性:被引⽤过⼀次的存储器位置会在未来被多次引⽤(通常在循环中)
  • 空间局部性:⼀个存储器的位置被引⽤,那么将来他附近的位置也会被引⽤

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

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

相关文章

光猫桥接模式详细步骤

目录 一、前言 路由模式 &#xff08;宽带默认&#xff09; 桥接模式 二、桥接模式步骤 &#xff08;一&#xff09;图片记录备份 设备信息图 网络侧信息 远程管理密码 宽带上网设置 &#xff08;二&#xff09;桥接模式开始 光猫设置 路由器设置 一、前言 重点&a…

2_5.Linux存储的基本管理

实验环境&#xff1a; 系统里添加两块硬盘 ##1.设备识别## 设备接入系统后都是以文件的形式存在 设备文件名称&#xff1a; SATA/SAS/USB /dev/sda,/dev/sdb ##s SATA, dDISK a第几块 IDE /dev/hd0,/dev/hd1 ##h hard VIRTIO-BLOCK /de…

sharding‐jdbc之分库分表(mysql主从同步的数据库安装和使用)

水平分表 创建基础工程.. 引入sharding‐jdbc的maven依赖包 注意需要数据库连接池等依赖 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1&l…

【JavaWeb】Day36.MySQL概述——数据库设计-DDL(三)

查询 关于表结构的查询操作&#xff0c;工作中一般都是直接基于图形化界面操作。 1.查询当前数据库所有表 2.查看指定表结构 3.查询指定表的建表语句 注意&#xff1a;23版的点击导航中的转到DDL 修改 关于表结构的修改操作&#xff0c;一般也是直接基于图形化界面操作。 添…

智能感应门改造工程

今天记录一下物联网专业学的工程步骤及实施过程 智能感应门改造工程 1 规划设计1.1 项目设备清单1.2项目接线图 软件设计信号流 设备安装与调试工程函数 验收 1 规划设计 1.1 项目设备清单 1.2项目接线图 软件设计 信号流 设备安装与调试 工程函数 工程界面: using System; …

【STM32】存储器和位带映射(bit band mapping)

文章目录 0 前言1 关于地址和存储器2 STM32内部存储器3 位带映射&#xff08;bit band mapping&#xff09;4 扩展&#xff1a;IAP 0 前言 最近在研究stm32标准库&#xff0c;对使用宏定义实现位操作的函数非常感兴趣&#xff0c;简单的一句PAout(1) 0;就能实现某个引脚电平的…

Linux离线安装python3(源码编译)

1、下载python包 下载python3.9.6的源码包 python下载 下载后&#xff0c;解压&#xff0c;目录如下&#xff1a; -rw-------. 1 root root 1454 Aug 26 2023 anaconda-ks.cfg -rw-r--r--. 1 root root 25640094 Apr 4 21:52 Python-3.9.6.tgz drwxrwxr…

前端三剑客 —— JavaScript (第一天)

目录 回顾内容 1.弹性布局 2.网格布局 JavaScript 概述 发展 浏览器 什么是Javascript JavaScript 能干什么 JavaScript需要的环境 JavaScript初体验 基本数据 JS书写方式 行内JS 页面JS 外部JS 1&#xff09;创建外部JS文件 2&#xff09;编写页面 对话框 警…

ubuntu-server部署hive-part2-安装hadoop

参照 https://blog.csdn.net/qq_41946216/article/details/134345137 操作系统版本&#xff1a;ubuntu-server-22.04.3 虚拟机&#xff1a;virtualbox7.0 安装hadoop ​​​​​​下载上传 下载地址 https://archive.apache.org/dist/hadoop/common/hadoop-3.3.4/ 以root用…

simulink的硬件支持下,串口发送的模型,stm32f407的串口程序调试错误

串口调试助手能接收到数据&#xff0c;为何是8个数据&#xff1f;如之奈何&#xff1f; 参考文章&#xff1a; STM32CubeMxMATLAB Simulink串口输出实验_用stm32cubemx生成的串口都是输出-CSDN博客根据 该文章发送字符串 hello&#xff0c;发送数量为5&#xff0c;接收也是he…

【PyQt5篇】多线程

文章目录 &#x1f354;使用QtDesigner进行设计&#x1f6f8;实现多线程&#x1f339;效果&#x1f50e;原因 &#x1f354;使用QtDesigner进行设计 对应的代码btn.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0">&l…

边界值设计测试用例

​ 边界值分析法&#xff08;Boundary Value Analysis&#xff0c;BVA&#xff09;的测试用例来自于等价类的边界&#xff0c;是等价类划分法的补充。根据边界值划分法&#xff0c;等价类分析法中的测试数据不是选取等价类中的典型值或任意值&#xff0c;而是应当选取正好等于、…

C++语言学习(三)——内联函数、auto、for循环、nullptr

1. 内联函数 &#xff08;1&#xff09;概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 内联函数是一种编译器指令&#xff0c;用于告诉编译器…

Web3 革命:揭示区块链技术的全新应用

随着数字化时代的不断发展&#xff0c;区块链技术作为一项颠覆性的创新正在改变着我们的世界。而在这一技术的进步中&#xff0c;Web3正逐渐崭露头角&#xff0c;为区块链技术的应用带来了全新的可能性。本文将探讨Web3革命所揭示的区块链技术全新应用&#xff0c;并展望其未来…

Redis从入门到精通(四)Redis实战(一)短信登录

文章目录 前言第4章 Redis实战4.1 短信登录4.1.1 基于session实现短信登录4.1.1.1 短信登录逻辑梳理4.1.1.2 创建测试项目4.1.1.3 实现发送短信验证码功能4.1.1.4 实现用户登录功能4.1.1.5 实现登录拦截功能4.1.1.6 session共享问题 4.1.2 基于Redis实现短信登录4.1.2.1 Key-Va…

顺子日期(结果填空)

为了解决这个问题&#xff0c;我们需要遍历2022年的每一天&#xff0c;并检查日期的每一位数字以查找顺子。下面是一个Java程序&#xff0c;用于计算2022年中的顺子日期数量&#xff1a; public class Main {public static void main(String[] args) {int count 0; for (int…

[StartingPoint][Tier0]Preignition

Task 1 Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (ii) dir busting, (iii) hash cracking. (目录暴力破解是一种用于检查 Web 服务器上的大…

leetcode代码记录(有效的字母异位词

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断它们是不是一组变位词&#xff08;字母异位词&#xff09;。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同且字符顺序…

【简单讲解下epoll】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

循环神经网络:揭秘长期记忆的魔法之源

在人工智能和机器学习领域&#xff0c;循环神经网络&#xff08;Recurrent Neural Networks&#xff0c;简称RNN&#xff09;以其独特的架构和机制&#xff0c;在处理序列数据方面展现出了强大的能力。特别值得一提的是&#xff0c;RNN能够学习到长期的记忆&#xff0c;这使得它…