6.15 操作系统面试题 锁 内存管理

自旋锁

自旋锁加锁失败后,线程会忙等待,直到它拿到锁。

需要注意,在单核 CPU 上,需要抢占式的调度器(即不断通过时钟中断一个线程,运行其他线程)。否则,自旋锁在单 CPU 上无法使用,因为一个自旋的线程永远不会放弃 CPU。

当加锁失败时,互斥锁用「线程切换」来应对,自旋锁则用「忙等待」来应对。

如果你能确定被锁住的代码执行时间很短,就不应该用互斥锁,而应该选用自旋锁,否则使用互斥锁。

死锁发生条件是什么?

  • 互斥条件
  • 持有并等待
  • 不可剥夺条件
  • 环路等待
    资源有序分配法

银行家算法

银行家算法是最有代表性的避免死锁的算法。

分配给进程资源前,首先判断这个进程的安全性,也就是预执行,判断分配后是否产生死锁现象。通过不断检查剩余可用资源是否满足某个进程的最大需求,如果可以则加入安全序列,并把该进程当前持有的资源回收;不断重复这个过程,看最后能否实现让所有进程都加入安全序列。

介绍一下操作系统内存管理

操作系统设计了虚拟内存,每个进程都有自己的独立的虚拟内存,我们所写的程序不会直接与物理内打交道。

分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。

虚拟地址与物理地址之间通过页表 来映射。

页表是存储在内存里的,内存管理单元 (MMU)就做将虚拟内存地址转换成物理地址的工作。

访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常 ,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。

分页不会有外部碎片,但会有内部碎片

页号+偏移量

讲一下段表?

虚拟地址也可以通过段表与物理地址进行映射的,分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有一个项,在这一项找到段的基地址,再加上偏移量。

虚拟地址是怎么转化到物理地址的?

在虚拟地址转换的过程中,通常会使用页表(Page Table)来进行映射。当程序访问一个虚拟地址时,MMU会将虚拟地址分解为页号和页内偏移量。

程序的内存布局是怎么样的?

  • 代码段,包括二进制可执行代码;
  • 数据段,包括已初始化的静态常量和全局变量;
  • BSS 段,包括未初始化的静态变量和全局变量;
  • 堆段,包括动态分配的内存,从低地址开始向上增长;
  • 文件映射段,包括动态库、共享内存等;
  • 栈段,包括局部变量和函数调用的上下文等。栈的大小是固定的,一般是 8 MB。

堆和栈的区别?

  • 堆是动态分配内存,由程序员手动申请和释放内存 ,通常用于存储动态数据结构和对象 。如果管理不当可能会导致内存泄漏或内存溢出 。堆通常比栈大,内存空间较大,动态分配和释放内存需要时间开销。
  • 栈是静态分配内存,由编译器自动 分配和释放内存,用于存储函数的局部变量和函数调用信息。遵循后进先出 的原则,变量的生命周期由其作用域决定 ,函数调用时分配内存,函数返回时释放内存。栈大小有限,通常比较小,内存分配和释放速度较快,因为是编译器自动管理。

fork()会复制哪些东西?

fork 阶段会复制父进程的页表(虚拟内存)

fork 之后,如果发生了写时复制 ,就会复制物理内存

当父进程或者子进程在向这个内存发起写操作 时,CPU 就会触发写保护中断 ,这个写保护中断是由于违反权限导致的,然后操作系统会在「写保护中断处理函数」里进行物理内存的复制 ,并重新设置其内存映射关系,将父子进程的内存读写权限设置为可读写,最后才会对内存进行写操作。

malloc 1KB和1MB 有什么区别?

如果用户分配的内存小于 128 KB,则通过 brk() 申请内存;

如果用户分配的内存大于 128 KB,则通过 mmap() 申请内存;

brk() 函数将「堆顶」指针向高地址移动,获得新的内存空间。

mmap() 系统调用中「私有匿名映射」的方式,在文件映射区分配一块内存

操作系统内存不足的时候会发生什么?

如果没有空闲的物理内存,那么内核就会开始进行回收内存的工作

OOM Killer 机制会根据算法选择一个占用物理内存较高的进程,然后将其杀死,以便释放内存资源

页面置换有哪些算法?

  • 最佳页面置换算法(OPT): 置换在「未来」最长时间不访问的页面。
  • 先进先出置换算法
  • 最近最久未使用的置换算法
  • 时钟页面置换算法
  • 最不常用置换算法
相关推荐
倔强青铜三8 分钟前
🚀LlamaIndex中文教程(1)----对接Qwen3大模型
人工智能·后端·python
小码编匠13 分钟前
基于 SpringBoot 开源智碳能源管理系统(EMS),赋能企业节能减排与碳管理
java·后端·开源
知其然亦知其所以然16 分钟前
Spring AI:ChatClient API 真香警告!我用它把聊天机器人卷上天了!
后端·aigc·ai编程
天天摸鱼的java工程师26 分钟前
彻底掌握Java Stream:覆盖日常开发90%场景附代码
后端
前端付豪1 小时前
美团路径缓存淘汰策略全解析(性能 vs 精度 vs 成本的三难选择)
前端·后端·架构
盛夏绽放1 小时前
Flask 中 make_response 与直接返回字符串的深度解析
后端·python·flask
Android洋芋2 小时前
Android开发实战:深度解析讯飞TTS原生库缺失崩溃问题及多引擎回退机制(附完整修复方案)
后端
Android洋芋2 小时前
Android平台TTS开发实战:从初始化失败到企业级优化的完整指南
后端
lovebugs2 小时前
百万并发下的生存之道:Java秒杀系统架构设计全解析
java·后端·架构
MrWho不迷糊2 小时前
用Java枚举类优雅实现订单状态机:告别“泥潭”式状态管理
后端·设计模式