【后端面试重点总结】操作系统篇(二)

参考:代码随想录八股、小林coding。

一、死锁及解决方式(参考代码随想录八股)

死锁:两个或多个进程在争夺系统资源时,由于互相等待对方释放资源而无法执行的状态

满足四个条件:①互斥条件:一个进程占用了某个资源时,其他进程无法同时占用。

②请求保持条件:一个进程申请资源时不会释放自己的资源。

③不可剥夺条件:资源不能从一个进程强制剥夺,只能由进程自己释放。

④环路等待:多个进程间形成一个循环等待的环,每个进程都在等待上一个进程释放资源。

解决方法:①一次性申请所有资源

②申请不到资源主动释放自己的资源

③按序申请,按序释放。

二、内存空间的扩充与分配

内存空间的扩充:①覆盖技术:程序分段,常用的段常驻内存,不常用的段需要时调入。

②交换技术:内存空间紧张时,将某些进程换出外存,在内存和磁盘动态调度。

③虚拟内存:实际内存不变,通过虚拟内存扩充。

连续分配管理方式:①单一连续分配:分成系统区和用户区,只能有一道用户程序。

②固定分区分配:用户区分成若干分区,多道程序。

③动态分区分配:根据进程大小动态分区。

非连续分配管理方式:①基本分页存储管理:将内存空间分为一个个大小相等的分区,页表来记录对应关系。

②基本分段存储管理:程序按照逻辑关系分为若干段,每个段在内存空间所占空间连续。

③段页式存储管理:将进程按逻辑模块分段,再将各段分页。

三、虚拟内存是什么?有什么好处?每个页大小(4KB/8KB)?(参考小林coding4.1 为什么要有虚拟内存? | 小林coding (xiaolincoding.com)

虚拟内存:操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来,程序所使用的内存地址叫做虚拟内存地址,实际存在硬件里面的空间地址叫物理内存地址,操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 芯片中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存,通过内存分段和内存分页方式管理虚拟内存和物理地址的关系。

作用:①虚拟内存可以使得进程对运行内存超过物理内存大小,因为程序运行符合局部性原理,CPU 访问内存会有很明显的重复访问的倾向性,对于那些没有被经常使用到的内存,我们可以把它换出到物理内存之外,比如硬盘上的 swap 区域。

②由于每个进程都有自己的页表,所以每个进程的虚拟内存空间就是相互独立的。进程也没有办法访问其他进程的页表,所以这些页表是私有的,这就解决了多进程之间地址冲突的问题

③页表里的页表项中除了物理地址之外,还有一些标记属性的比特,比如控制一个页的读写权限,标记该页是否存在等。在内存访问方面,操作系统提供了更好的安全性。

四、什么是内存分段和内存分页?不足?解决方法?

内存分段:将一个程序的内存空间分为不同的逻辑段,每个段代表程序的一个功能模块或数据类型,如代码段、数据段、堆栈段等,每个段有自己的大小和权限。

虚拟地址构成:段选择因子段内偏移量,段选择子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。

映射方式:虚拟地址是通过段表与物理地址进行映射的,分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有一个项,在这一项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址。

不足:①内存碎片:内存分段管理可以做到段根据实际需求分配内存,所以有多少需求就分配多大的段,所以不会出现内部内存碎片。由于每个段的长度不固定,所以多个段未必能恰好使用所有的内存空间,会产生了多个不连续的小物理内存,导致新的程序无法被装载,所以会出现外部内存碎片的问题。

解决方法:通过内存交换来解决外部内存碎片的问题,可以把音乐程序占用的那 256MB 内存写到硬盘上,然后再从硬盘上读回来到内存里。不过再读回的时候,我们不能装载回原来的位置,而是紧紧跟着那已经被占用了的 512MB 内存后面。这样就能空缺出连续的 256MB 空间,于是新的 200MB 程序就可以装载进来。

内存交换的缺点:因为硬盘的访问速度要比内存慢太多了,每一次内存交换,我们都需要把一大段连续的内存数据写到硬盘上。所以,如果内存交换的时候,交换的是一个占内存空间很大的程序,这样整个机器都会显得卡顿。

内存分页:分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小,这样一个连续并且尺寸固定的内存空间,我们叫Page)。在 Linux 下,每一页的大小为 4KB。虚拟地址与物理地址之间通过页表来映射。

映射方式:在分页机制下,虚拟地址分为两部分,页号页内偏移。页号作为页表的索引,页表包含物理页每页所在物理内存的基地址,这个基地址与页内偏移的组合就形成了物理内存地址。

转换流程:把虚拟内存地址,切分成页号和偏移量;根据页号,从页表里面,查询对应的物理页号;直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。

碎片问题:采用了分页,页与页之间是紧密排列的,所以不会有外部碎片。因为内存分页机制分配内存的最小单位是一页,即使程序不足一页大小,我们最少只能分配一个页,所以页内会出现内存浪费,所以针对内存分页机制会有内部内存碎片的现象。

简单分页缺陷:有空间上的缺陷,会占用很大的空间,在 32 位的环境下,虚拟地址空间共有 4GB,假设一个页的大小是 4KB(2^12),那么就需要大约 100 万 (2^20) 个页,每个「页表项」需要 4 个字节大小来存储,那么整个 4GB 空间的映射就需要有 4MB 的内存来存储页表。这 4MB 大小的页表,看起来也不是很大。但是要知道每个进程都是有自己的虚拟地址空间的,也就说都有自己的页表。那么,100 个进程的话,就需要 400MB 的内存来存储页表,这是非常大的内存了,更别说 64 位的环境了。

解决方法:多级页表,使用了二级分页,一级页表就可以覆盖整个 4GB 虚拟地址空间,但如果某个一级页表的页表项没有被用到,也就不需要创建这个页表项对应的二级页表了,即可以在需要时才创建二级页表。做个简单的计算,假设只有 20% 的一级页表项被用到了,那么页表占用的内存空间就只有 4KB(一级页表) + 20% * 4MB(二级页表)= 0.804MB。页表一定要覆盖全部虚拟地址空间,不分级的页表就需要有 100 多万个页表项来映射,而二级分页则只需要 1024 个页表项,此时一级页表覆盖到了全部虚拟地址空间,二级页表在需要时创建。

段页式内存管理:先将程序划分为多个有逻辑意义的段,也就是前面提到的分段机制,接着再把每个段划分为多个页,也就是对分段划分出来的连续空间,再划分固定大小的页,地址结构就由段号、段内页号和页内位移三部分组成。第一次访问段表,得到页表起始地址;第二次访问页表,得到物理页号;第三次将物理页号与页内位移组合,得到物理地址。

  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值