面经(二)内存管理

这篇博客深入探讨了操作系统内存管理,包括单一连续存储、操作系统分区、伙伴系统、覆盖、交换等概念,以及页式和段式内存管理。同时,讨论了内存分区、堆栈的区别、内存池、深浅拷贝、移动和拷贝的差异,以及动态内存分配的操作系统行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

操作系统内存管理概述

单一连续存储

早期的程序计算机指令访问的内存地址直接就是物理地址,内存的管理方法是单一连续存储管理,内存被分为系统区和用户区,应用程序被放在用户区运行

操作系统分区

固定分区&动态分区

为了支持多道程序,多个程序并发执行,引入了分区操作系统,把内存分为很多区,操作系统占一个区,还剩下了好多个区,每个程序占一个或几个区,但不能进行内存共享,会产生内外碎片,静态分区每个区大小相同,动态分区每个区大小不同,根据程序需要操作系统动态分配大小,没有内碎片,但有外碎片

伙伴系统

为了综合考虑固定分区和静态分区,引入了伙伴系统,分区大小均为2 ^ k大小,1≤k≤m,最开始一块分区,大小为2 ^ m,大小相同的分区,用同一个链表维护,当需要分配一个长度为n的连续空间时,找到最能满足的大小,在对应的空闲分区链表中查找,如果找到了就分配,如果没有找到就找大一号的,如果在大一号的里面找到了,那把大一号的拆分成两个小一号的,把一个分配出去,把另一个放进空闲链表里,回收的时候如果是拆出来的,那么回收后把两个小一号的合并成大一号的

覆盖

在多道程序技术中,还有一个问题是,如果现在可用内存确实很小,程序员在写程序时会对程序分区,分为常驻内存和可选部分,可选部分平时存放在覆盖文件中,需要时才装入内存

交换

为了解决同样的问题,另一种方法是交换技术,整个程序不再需要划分,而是直接把不能运行的程序换出内存,这样获得的空闲内存用来跑新程序或外存里就绪的老程序

离散内存管理

这些思想都基于程序的运行需要在一段连续的内存地址内,这样的问题在于,可能物理地址有很大,但1.在32位机里,cpu只能寻址2^32个地址也就是4G,因此会有些浪费,2.当内存里运行了多个程序后,内存里都是碎片内存,3.各个进程之间共享一个物理内存,一个进程可以恶意修改别的进程的信息4.现代操作系统需要实现内存的访问控制,有的地址不是谁都能访问的,5.当一个进程在运行时,另一个进程抢占了,此时原进程需要被全部拷贝到硬盘中,然后将新程序装入内存中运行(交换)。
因此提出了将程序放在不连续的地址空间内的思想

页式

页式存储管理的思想是把内存和物理内存都划分为相同大小的分页,每个程序的内存地址和实际物理地址一样大,每个程序有一个页表,用来记录自己的页对应在物理地址中的页在哪,当然每个程序都维护一个页表是不现实的,因此实际上还有二级页表三级页表
因此,操作系统为了维护内存,给每个进程都分配4G大小的内存,这4G的虚拟地址和实际的物理地址,先被分为相同大小的一页一页(例如4k),通过页表,建立逻辑地址与物理地址之间的关系,根据程序的局部性原理,当一块内存被访问时,可能附近的内存也要被访问,因此这个页表里并不是每个逻辑地址都真的映射物理地址,只有部分确实有映射,其余页表的数据被保存在硬盘里(swap & C),当访问某一页没有映射时就会缺页中断,操作系统就赶紧把硬盘里的数据拿出来放到物理内存里,并建立好映射关系,如果确实没有空闲内存了,那就涉及到页面置换算法

段式

另一种内存管理思想是不把程序内存和物理内存分页,而是像动态分配一样,只是把程序的地址空间分为若干个段,各个段依据动态分配的思想分配,而程序整体的地址空间不必连续


############################################################################


内存分区

代码段 只读数据(字符串常量)、文本存储(程序机器代码)
数据段 已初始化的全局变量和静态变量
bss段 未初始化的全局变量和静态变量以及初始化为0的全局变量和静态变量
堆区 new malloc出来的
栈区 函数、局部变量

hello world在哪个区:
文字常量区

堆和栈的区别

栈和堆的生长方向为啥不同

程序的地址空间从低地址到高地址的顺序依次是程序、数据、堆、栈、环境参数变量,堆和栈之间有很大一部分地址空间,如果堆和栈刚好相向生长就不用管堆栈中间的分界线了

内存池

深浅拷贝

浅拷贝就是指,当我们拷贝对象的时候,两个对象的指针指向了同一个内容,这时候不论是析构还是改变这个内容的值都会出错,而深拷贝是指,两个对象指向两个不同的地址,但这个地址里的内容都是一样的,具体做法是利用原对象的构造函数构造一个temp,构造函数不仅会开空间还会数据拷贝,然后将temp的指针和目的对象的指针交换即可

移动和拷贝的区别

对于不含指针的类,移动和拷贝都是值的复制,对于含有指针的类,移动与拷贝相似,只是移动会把原指针置为nullptr

申请动态内存时操作系统怎么做

malloc在分配时,实际上分配的空间大小为:用户需要的空间+用来管理的空间,一般需要满足[用户空间+sizeof(控制块)]%16 == 0。在操作系统中,所有的块都有一个用于管理的数据结构,用来记录该内存块是否可用以及块的大小,
因此malloc的过程为:先在堆中找空闲的内存块,如果找到了空闲,那么大小是否满足,如果满足直接用,如果一直没找到,那就向操作系统申请新的内存(sbrk),把新的内存加到堆中,如果申请失败,直接返回NULL,如果有,那么越过内存控制块的大小,把实际地址返回给用户, free操作相反,直接把内存块的可用信息设置为可用就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱骥伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值