当前位置: 首页 > news >正文

操作系统系统面试常问(内存、快表、相关知识)

内存的覆盖是什么?有什么特点?

内存覆盖是一种动态内存管理技术,它将程序划分为固定区和覆盖区。固定区存放核心代码和常用数据,覆盖区则按需加载当前需要的非核心模块。当程序需要执行新功能时,系统会将对应模块从外存调入覆盖区,替换掉不再使用的模块。这种技术突破了程序必须全部装入内存才能运行的限制,允许运行比物理内存更大的程序。但要注意只有覆盖区的模块可以被替换,固定区的内容会常驻内存。覆盖技术通过按需加载机制有效提高了内存利用率,特别适合早期内存资源有限的系统环境。

内存交换是什么?有什么特点?

交换(对换)技术的设计思想:内存空间紧张时,系统将内存中某些进程暂时换出外存,把外存中某些已具备运⾏条
件的进程换⼊内存(进程在内存与磁盘间动态调度)
换⼊:将内存中暂时不运行的进程(如阻塞态、低优先级)整体移至磁盘交换区,腾出物理内存空间。
换出:当需要运行被换出的进程时,再将其从磁盘完整载回内存,恢复执行。

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

内存交换技术利用磁盘对换区暂存被换出的进程数据,采用连续分配方式提升I/O速度。与追求空间利用率的文件区不同,对换区通过牺牲部分存储效率来换取更快的进程切换性能,当内存不足时将不活跃进程换出到对换区,需要时快速换入,从而扩展可用内存空间。

在发生内存交换时,有些进程是被优先考虑的?你可以说⼀说吗?

1、可优先换出阻塞进程
2、可换出优先级低的进程
3、为了防⽌优先级低的进程在被调⼊内存后很快⼜被换出,有的系统还会考虑进程在内存的驻留时间… (注意: PCB 会常驻内存,不会被换出外存)

内存交换你知道有哪些需要注意的关键点吗?

1、交换需要备份存储,通常是快速磁盘,它必须⾜够⼤,并且提供对这些内存映像的直接访问。
2、为了有效使⽤CPU,需要每个进程的执⾏时间⽐交换时间⻓,⽽影响交换时间的主要是转移时间,转移时间与所交换的空间内存成正⽐。
3、如果换出进程,⽐如确保该进程的内存空间成正⽐。
4、交换空间通常作为磁盘的⼀整块,且独⽴于⽂件系统,因此使⽤就可能很快。
5、交换通常在有许多进程运⾏且内存空间吃紧时开始启动,⽽系统负荷降低就暂停。
6、普通交换使⽤不多,但交换的策略的某些变种在许多系统中(如UNIX系统)仍然发挥作⽤。

说⼀下你理解中的内存?他有什么作用呢?

内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被CPU处理。
问题:如果多个程序数据需要同时放入到内存中,那么如何区分各个程序的数据放在哪个地方?
方法:给内存的存储单元编地址,内存地址是从0开始,每个地址对应一个存储单元(如果计算机按字节编址,则每个存储单元大小为1字节,即1B,及8个二进制位,如果字长位16位的计算机按字编址,则一个存储单元为1个字;每个字为16个二进制位)

操作系统在对内存进行管理的时候需要做些什么?

1、操作系统负责内存空间的分配与回收。
2、操作系统需要提供某种技术从逻辑上对内存空间进⾏扩充。
3、操作系统需要提供地址转换功能,负责程序的逻辑地址与物理地址的转换。
4、操作系统需要提供内存保护功能。保证各进程在各⾃存储空间内运⾏,互不⼲扰

Windows和Linux环境下内存分布情况

在这里插入图片描述
1、程序⽂件段,包括⼆进制可执⾏代码;
2、已初始化数据段,包括静态常量;
3、未初始化数据段,包括未初始化的静态变量;
4、堆段,包括动态分配的内存,从低地址开始向上增⻓;
5、⽂件映射段,包括动态库、共享内存等,从低地址开始向上增⻓(跟硬件和内核版本有关)
6、栈段,包括局部变量和函数调⽤的上下⽂等。栈的⼤⼩是固定的,⼀般是 便我们⾃定义⼤⼩;

⼀个由C/C++编译的程序占用的内存分为哪几个部分?

1、栈区(stack)— 地址向下增⻓,由编译器⾃动分配释放,存放函数的参数值,局部变量的值等。其操作⽅式类似于数据结构中的队列,先进后出。
2、堆区(heap)— 地址向上增⻓,⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配⽅式倒是类似于链表。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在⼀块的,初始化的全局变量和静态变量在⼀块区域,未初始化的全局变量和未初始化的静态变量在相邻的另⼀块区域。 - 程序结束后有系统释放
4、⽂字常量区 —常量字符串就是放在这⾥的。程序结束后由系统释放
5、程序代码区(text)—存放函数体的⼆进制代码。

常见内存分配方式有哪些?

1、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运⾏期间都存在。例如全局变量,static变量。
2、在栈上创建。在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内存容量有限。
3、从堆上分配,亦称动态内存分配。程序在运⾏的时候⽤malloc或new申请任意多少的内存,程序员⾃⼰负责在何时⽤free或delete释放内存。动态内存的⽣存期由我们决定,使⽤⾮常灵活,但问题也最多。

常见的内存分配内存错误

1、内存分配未成功,却使⽤了它(编程新⼿常犯这种错误,因为他们没有意识到内存分配会不成功。常⽤解决办法是,在使⽤内存之前检查指针是否为NULL)
2、内存分配虽然成功,但是尚未初始化就引⽤它(以⽆论⽤何种⽅式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦)
3、内存分配成功并且已经初始化,但操作越过了内存的边界(例如在使⽤数组时经常发⽣下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界)
4、忘记了释放内存,造成内存泄露(动态内存的申请与释放必须配对,程序中malloc与free的使⽤次数⼀定要相同,刚开始时系统的内存充⾜,你看不到错误。终有⼀次程序突然挂掉,系统出现提示:内存耗尽)
5、释放了内存却继续使⽤它(函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引⽤”,因为该内存在函数体结束时被自动销毁。使⽤free或delete释放了内存后,没有将指针设置为NUL。)

从堆和栈上建立对象哪个快?(考察堆和栈的分配效率比较)

从两⽅⾯来考虑:
1、分配和释放,堆在分配和释放时都要调⽤函数(malloc,free),⽐如分配时会到堆空间去寻找⾜够⼤⼩的空间(因为多次分配释放后会造成内存碎⽚),这些都会花费⼀定的时间,具体可以看看malloc和free的源代码,函数做了很多额外的⼯作,而栈却不需要这些。
2、访问时间,访问堆的⼀个具体单元,需要两次访问内存,第⼀次得取得指针,第⼆次才是真正的数据,而栈只需访问⼀次。另外,堆的内容被操作系统交换到外存的概率⽐栈⼤,栈⼀般是不会被交换出去的。

⼀个程序从开始运行到结束的完整过程,你能说出来多少?

预编译

主要处理源代码⽂件中的以“#”开头的预编译指令。处理规则⻅下:
1、宏替换:所有 #define 定义的宏会被直接替换成对应的值或代码,不会保留宏名。
2、条件编译处理:#if、#ifdef、#elif、#else、#endif 等指令会被解析,仅保留符合条件的代码块,其余部分移除。
3、头文件展开:#include 指定的文件内容会被递归插入到当前文件,形成完整的待编译代码。
4、删除注释:所有 // 单行注释和 /* */ 多行注释都会被移除。
5、保留 #pragma 指令:如 #pragma once 等编译器特殊指令会被保留,它们可能影响编译行为(如防止重复包含)。
6、添加行号标记:编译器会插入行号和文件名信息,便于调试和错误定位。

编译

把预编译之后⽣成的xxx.i或xxx.ii⽂件,进⾏⼀系列词法分析、语法分析、语义分析及优化后,⽣成相应的汇编代
码⽂件。
1、词法分析:将代码拆解成记号(如标识符、关键字、运算符等),类似于“分词”过程。
2、语法分析:根据语法规则,将记号组合成语法树,检查代码结构是否正确(如括号匹配、语句格式)
3、语义分析:检查变量类型、作用域等静态语义,确保表达式合法(如 int a = “hello”; 会报错)。
4、优化:对代码进行简化(如删除无用计算、常量折叠),提升运行效率。
5、生成汇编代码:将优化后的中间代码转换为目标机器的汇编指令。
6、汇编代码优化:调整寻址方式、简化指令等,进一步提高性能。

汇编

汇编器(如 as)将汇编代码(.s)逐行翻译成机器码,生成目标文件(Linux 下 .o,Windows 下 .obj)。这一过程是直接对照汇编指令与机器码的映射表转换,不涉及语法分析或优化。生成的文件已经是二进制格式,可直接用于后续链接。

链接

将不同的源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。链接分为静态链接和动态链接:
1、静态链接:
静态链接在编译时将库函数和数据直接复制到最终的可执行文件中。这种方式会导致每个程序都包含所需库的完整副本,造成存储空间浪费,特别是多个程序使用相同库时会在内存中存在重复副本。另一个缺点是库更新时需要重新编译整个程序。不过静态链接的优势在于运行时无需加载外部库,因此执行速度更快。
2、动态链接:
动态链接采用运行时加载的方式,将程序模块在运行时才进行链接。多个程序可以共享同一个库文件的内存副本,避免了静态链接的空间浪费问题。当库需要更新时,只需替换库文件即可,无需重新编译程序,大大简化了维护工作。不过由于需要在程序运行时进行链接,会带来一定的性能开销。这种机制在节省内存和方便更新方面具有明显优势,但以轻微的性能损失为代价。

动态分区分配算法有哪⼏种?可以分别说说吗?

1、⾸次适应不仅最简单,通常也是最好最快,不过⾸次适应算法会使得内存低地址部分出现很多⼩的空闲分区,⽽每次查找都要经过这些分区,因此也增加了查找的开销。2、邻近算法试图解决这个问题,但实际上,它常常会导致在内存的末尾分配空间分裂成⼩的碎⽚,它通常⽐⾸次适应算法结果要差。3、最佳导致⼤量碎⽚。4、最坏导致没有⼤的空间。进过实验,⾸次适应⽐最佳适应要好,他们都⽐最坏好。
在这里插入图片描述

逻辑地址VS物理地址

编译时只需确定变量x存放的相对地址是100 ( 也就是说相对于进程在内存中的起始地址⽽⾔的地址)。 CPU想要找到x在内存中的实际存放位置,只需要⽤进程的起始地址+100即可。相对地址⼜称逻辑地址,绝对地址⼜称物理地址。

http://www.lryc.cn/news/605689.html

相关文章:

  • 关于npm前端项目编译时栈溢出 Maximum call stack size exceeded的处理方案
  • 专业鼠标点击器,自定义间隔次数
  • NPM打包时,报reason: getaddrinfo ENOTFOUND registry.nlark.com
  • 从Excel到工时管理系统:企业如何选择更高效的工时记录工具?
  • Verilog实现RPC从机(配合AXI_Slave使用)
  • 金融专题|某跨境支付机构:以榫卯企业云平台 VPC 功能保障业务主体安全
  • 查询目前服务器所占的带宽的命令(上传和下载)
  • TTS语音合成|f5-tts语音合成服务器部署,实现http访问
  • 【Kiro Code 从入门到精通】重要的功能
  • 安全月报 | 傲盾DDoS攻击防御2025年7月简报
  • python中高效构建提示词
  • 关于PHP学习
  • 【BUG】nvm无法安装低版本Node.js:The system cannot find the file specified解决方案
  • iOS15及以后国际化如何设置.xcstrings文件默认语言
  • Jmeter全局变量跨线程组的使用
  • ShimetaPi M4-R1:国产高性能嵌入式平台的异构计算架构与OpenHarmony生态实践
  • Video Pixel Repetition
  • Spring AI MCP 技术从使用到项目实战深度解析
  • 数据结构:多项式加法(Polynomial Addition)
  • Linux多线程线程控制
  • PHP开发
  • 《质光相济:Three.js中3D视觉的底层交互逻辑》
  • Redis高频问题全解析
  • 深度理解 linux 系统内存分配
  • [特殊字符] 数字孪生 + 数据可视化:实战经验分享,让物理世界数据 “会说话”
  • Java【代码 21】将word、excel文件转换为pdf格式和将pdf文档转换为image格式工具类分享(Gitee源码)aspose转换中文乱码问题处理
  • ubuntu24.04环境下树莓派Pico C/C++ SDK开发环境折腾记录
  • STM32学习记录--Day4
  • 云原生运维与混合云运维:如何选择及 Wisdom SSH 的应用
  • AI编程新工具!使用 LangGraph 构建复杂工作流