Frederick

Welcome to my Alter Ego's site!

Apr 5, 2025 - 15 minute read - Comments

OS

引导程序:当计算机开机运行时,需要运行一个初始程序,位于计算机的固件,如只读内存ROM,将操作系用内核加载到内存中,除了内核外,一些服务也会在启动时加到内存成为系统程序或后台,一旦完成,系统完全启动,等待事件发生(如触发一个软件)

中断:事件发生通常通过硬件或软件的中断来通知,硬件可以通过系统总线发送信号到CPU,以触发中断,软件可以通过执行系统调用(systemcall)触发中断

存储结构

内存,即随机访问内存RAM,或动态随机访问内存(不一定连续),DRAM

只读内存,ROM,数据不可修改,不可写。

内存有易失性

外存:非易失性,数据可持久化

寄存器->高速缓存->内存->固态磁盘->硬盘->光盘->磁盘

I/O结构

pass

从处理器数量分类:

  • 单处理器系统:执行一个通用指令集,该指令集包括执行用户进程的指令,而专用处理器执行有限的指令集

  • 多处理器系统:多核系统,集成多个计算机到单个芯片的系统

内存->CPU*n(寄存器,高速缓存)

(一个芯片上)多处理器系统的特点:增加吞吐量,规模经济(对于生产商而言),增加可靠性

非对称性处理器:一个主处理器控制系统,其他处理器或向主处理器要任务或处理预先规定的任务,成为主从关系,主处理器调度从处理器,安排任务

对称处理器:每个处理器都参与完成操作系统的所有任务,没有主从关系

  • 集群系统:系统将多个CPU组合在一起,一般通过网络链接,提供高可用性的服务

操作系统的执行

多道程序能力:单个程序不能让CPU和IO设备始终忙碌,多道程序通过安排作业,使得CPU总有一个执行作业,从而提高CPU利用率。

解释下多道程序:批处理系统下有多个作业,双击qq会先放到磁盘里面一个叫做作业池的地方,准备执行,加载程序时,将作业池拿到内存里开始运行,在内存里,这些作业叫做进程(执行中的程序),就是把硬盘中的二进制文件加载到了内存中,CPU来切换执行多个进程(因为CPU的速度非常快,但一次只能执行一条指令,有大量时间空闲,这样做可以提高CPU利用率)

为什么先要保存到磁盘的作业池?

内存太小不能容纳所有作业,所有作业首先保存到磁盘的作业池,

分时系统:是多道程序设计的自然延伸,对于分时系统,CPU通过切换作业执行多个作业,由于切换频率很高,用户可以在程序运行时与其交互。分时需要确保响应时间。

解释伪并行的本质:CPU执行每个作业一个时间片,但因为切换上下文的非常快,几乎感受不出来,以至于认为是并行

双重模式与多重模式的执行

操作系统是中断驱动的,事件是由中断或陷阱/异常引起的,陷阱是一种软件生成的中断,或源于出错,源于用户程序的特定请求

为确保os的正确运行,必须区分操作系统代码和用户代码的执行

  • 用户模式和内核模式

计算机硬件可以通过模式为来表示当前模式:内核模式0和用户模式1

当计算机系统执行用户应用时,系统处于用户模式,当用户应用通过系统调用,请求操作系统服务时,系统必须从用户模式切换到内核模式

解释系统调用:用户想要调用硬件,OS提供一些接口(API,对外提供服务)

解释用户模式到内核模式的调用:用户进程执行->调用系统调用(触发陷阱,陷阱模式位设置位0,执行系统调用)->执行系统调用(内核模式)->(返回模式位=1)->从系统调用返回(用户模式),切换的过程耗时,浪费性能,尽量减少用户模式到内核模式的切换

为什么需要系统调用?

双重模式执行提供保护手段,以便防止操作系统和用户程序收到错误用户程序的影响,这种防护实现为,将可能引起损害的机器指令作为特权指令,并且硬件只有在内核模式下才允许执行特权指令,如果在用户模式下试图执行特权指令(直接调用硬件),那么硬件并不执行该指令,而是认为该指令非法,并将以陷阱形式通知操作系统

定时器设置的意义?

操作系统应该维持控制CPU,防止用户程序陷入死循环,或者不调用系统服务并且不将控制返回给操作系统,为了实现这一目标可以使用定时器,设定为指定周期后中断计算机。

进程管理

在未被CPU执行之前,程序做不了任何事情,执行中的程序称为而进程,因为程序是被动实体,只有加载到内存中,成为进程才是主动实体

单线程进程有一个程序计数器,指定了下一个所要执行的指令

进程是系统的工作单元,系统由多个进程组成,其中由操作系统进程,也有用户进程,所有进程并发执行

为什么需要内存管理?

为了改进CPU的利用率和用户的计算机响应速度,计算机应在内存中保留多个程序,这就需要内存管理。

操作系统负责内存管理的以下活动

  • 记录内存的哪部分被使用以及谁在使用
  • 决定哪些进程会调入调出内存
  • 根据需要分配和释放内存空间

高速缓存

为什么需要高速缓存?高速缓存一般集成在CPU中,比起重新去内存中调用,速度更快

高速缓存的大致原理?在去内存取数据之前,会先到高速缓存中看一下有没有数据,如果没有,去内存中取,放到高速缓存中一份,再拿到CPU中

高速缓存的数据一致性问题?如果内存中数据改变,必须保证高速缓存中对应数据失效,否则不一致

多级高速缓存?一级缓存最靠近CPU,最快最小

例:整数A从磁盘到寄存器的迁移:硬盘->内存->高速缓存->硬件寄存器

I/O系统

I/O子系统为操作系统本身隐藏了IO设备的特性

IO子系统包括以下几个组件:缓冲,高速缓存的内存管理组件;USB;硬件驱动程序

只有设备驱动程序才知道控制设备的特性

计算环境

传统计算

移动计算:只能手机或平板电脑的计算

分布计算:分布式系统是物理上分开的,通过网络相连的一组计算机系统

客户机-服务器计算

对等计算:不区分客户机和服务器

云计算:虚拟化技术的延伸

虚拟化

通过虚拟化,操作系统可以在其他操作系统上运行应用程序

无虚拟化:进程->内核->硬件

虚拟化:进程->内核->VM->虚拟机管理器->硬件

操作系统的服务

用户和其他系统程序->用户界面->系统调用->服务->操作系统->硬件

用户界面:GUI和命令解释程序,即shell,将用户输入的命令转换为机器指令,占用资源更少

系统调用

系统调用提供操作系统服务接口,这些调用通常以高级语言编写or汇编?

例:一个简单的复制文件的操作(获取输入文件名称,写提示到屏幕,接受输入,获取输出文件名称,写提示到屏幕,接受输入,打开输入文件,如果不存在,终止,创建输出文件,如果存在,终止,循环,读取输入文件,写到输出文件,直到读取失败,关闭输出文件,写完成消息到屏幕,正常终止)

用户应用程序(如C++,C)使用open()调用系统调用接口,切换到内核模式,底层硬件实行

系统调用的类型:进程控制,文件管理,设备管理,信息维护,通信和保护

进程控制

如果一个系统调用异常或暂停当前执行的程序,会存储内存到磁盘,并生成错误信息

锁的意义?

多进程中,多个进程会共享数据,为了确保共享数据的完整性 ,操作系统通常提供系统调用->允许一个进程锁定共享数据,这样在结束前,其他进程不能访问该数据

例:MS-DOX

可用内存->进程->命令解释程序->内核

操作系统的结构

封装子系统模块

采用为内核技术的具体实现和好处?

对内核进行模块化,把不必要的部件从内核中移除,将他们当作系统级和用户级的程序来实现,结果是内核较小

微内核的主要功能是,为客户端程序和运行在用户空间中的各种服务提供通信

优点:便于移植和拓展(部件)

缺点:增加模式切换,增加系统功能开销

目前操作系统采用可加载的内核模块:需要哪些就加载哪些(比如调度类,文件系统,设备和总线驱动程序)

进程管理

现代操作系统允许加载多个程序到内存,以便并发执行,进程即执行中的程序,进程是现代分时操作系统的工作单元

并发执行:通过在进程之间切换CPU

当一个可执行文件被加载到内存时,这个程序就成为进程,进程时执行中的程序实体,相同一份代码可以有多个程序实体(进程),进程是操作系统进行资源分配和调度的基本单位

但是,进程不只是程序代码,进程还包括当前活动,PC的值和寄存器的内容

进程状态

就绪 运行 等待

进程状态图

pass

进程控制块(PCB)包含许多某个特定进程相关信息,包括新城状态,程序计数器(下一个指令地址),CPU寄存器,CPU调度信息…….本质就是保存上下文信息

进程键CPU切换

执行->中断->保存状态到PCB1->从PCB1重新加载状态->执行->中断->保存转台到PCB1->从PCB1更新加载状态->执行

单线程:每个进程一次只能执行一个任务

  • 进程调度

表示进程调度的队列图

pass

操作系统通过调度程序来选择进程而后执行进程

  • 长期调度程序:如批处理系统,将进程保存到类似磁盘的大容量存储设备
  • 短期调度程序:从内存中准备执行的进程中许纳泽进程,并分配CPU执行
  • 中期调度程序:将进程从内存(或CPU竞争中)移除,从而降低多道程序调度,之后进程可以被重新载入内存,并从中断处继续执行,称之为交换(换出,换入)

IO密集型:执行进程时,IO占用更多的时间,可能要等待IO

CPU密集型:执行进程时,CPU计算占用更多时间

上下文切换:

pass

进程运行

并行与并发区别?单核上并发:CPU上下切换(策略),毕竟单CPU一个时间只能执行一个进程。并行:多核,执行多个进程

sleep()放弃执行,但CPU此时选择其他进程不一定切换一个不一样的

  • 多线程模型

用户线程

内核线程

  • 多对一模型

为什么不用多对一模型?容易阻塞(一个线程阻塞影响所有)不允许运行在多处理器上

  • 一对一模型

支持并发,但是开销影响性能

  • 多对多模型

多对并发,相对于多对一模型,阻塞时允许调用另一个线程

  • 双层模型

线程池优点?

进程调度

CPU是如何选择进程的?

单处理器:

多道程序

当一个进程等待时,交出CPU

进程包括CPU执行和IO等待,两者交替

IO密集型&CPU密集型

抢占调度

等待状态和就绪状态?等待状态缺少IO和CPU,就绪就只缺少CPU

抢占型和非抢占型

调度程序

比较CPU调度算法准则:CPU使用率,吞吐量,周转时间,等待时间,响应时间

最大化CPU使用率和吞吐量,最小化周转时间,等待时间和响应时间

抢占式内核

非抢占式内核

调度算法

先到先服务FCFS

使用队列FIFO实现,当一个进程进入队列时,它的PCB会被连接到队列尾部,当CPU空闲时,它会分配给头部的进程

非抢占式,平均等待时间比较长

最短作业优先调度

SJF(shortest-job-first)

优点:平均等待时间最小,性能最好

QA:如何知道下次CPU执行系列?

对于批处理系统的长期调度,…

对于短期CPU调度,…

可以是抢占式或非抢占式,依据到达时间,执行时间(delta即为剩余时间)

抢占SJF调度称为最短剩余时间优先调度

优先级调度

每个进程都有一个优先级关联,具有最高优先级的进程会分配到CPU,先攻优先级的进程按FCFS.SJF算法优先级位下次CPU执行的倒数,CPU执行越长,优先级越小

但并不是优先级数值越小,优先级越高!(可能是越大)

  • 主要问题:无穷堵塞/饥饿问题

解决方法:老化:增加在系统中等待很长时间的进程的优先级

轮转调度

RR

专门位分时系统设计,增加了抢占时间片切换进程,每个进程分配不超过一个时间片的CPU执行

抢占,性能取决于时间片大小,如果时间片很大,类似于FCFS(实际进程执行小于时间片),如果时间片很小,导致频繁的上下文切换(性能消耗)

多级队列调度

根据属性,将一个进程永久放到一个队列

优先级高的队列先执行,可能会有饥饿问题

多级反馈调度

允许进程在队列之间切换,阻止饥饿发生

  • 为什么将IO密集型放在更高优先级队列而不是CPU密集型?

因为IO密集型比较耗时,CPU比较空闲,根据反馈调度,CPU更有时间去执行优先级较低的

多处理器调度

之前讨论的都是单处理器

非对称处理器:一个处理器处理所有调度决定,IO处理等系统活动,其他处理器只执行用户代码,简单,减少数据共享需要

多对称处理器SMP:每个处理器自我调度,都有私有就绪进程队列

处理器亲和性:试图让一个进程运行在一个处理器上

  • 如果进程转移到其他处理器会发生什么?

一个处理器缓存无效,第二个重新填充

负载平衡:尽量将所有负载平衡分配到SMP每个处理器上,两种方法:推迁移和拉迁移,两种并行实现,但会抵消处理器亲和性的好处

实时CPU调度

软实时和硬实时系统,硬实时系统必须保证以恶搞任务再它的戒指期限之前完成

实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。

最小化延迟

中断延时:先完成正在执行的指令,再确定中断类型(IOor时间片没?),保存当前进程状态,采用特定的中断服务程序(ISR),上下文切换,这些总时间是中断延迟

调度延时:从停止一个进程到启动另一个进程所需的时间量

!尽量减少中断延迟,确保实时任务得到尽快处理

  • 如何减少调度延迟?

提供抢占式内核

  • 调度延迟的冲突部分

优先权调度

进程周期性,定期需要CPU,具有固定的处理时间t,CPU应处理的截止期限d和周期p(比如时间片)

为什么硬实时系统处理时间要小于截止时间而不是小于周期?系统开销(比如延时)

硬实时:0<=t<=d<=p

t执行时间就是CPU运行时间,CPU利用率就是t/p

单调速率调度

抢占的,静态优先级

最优,但是CPU利用率是有限的,并不总是可能完成最大化CPU资源

最早截止期限优先调度

EDF,动态分配优先级

比例分享调度

准入控制策略:只有客户请求的股数小于可用的股数,才能允许客户进入

同步

解决共享数据并发访问导致数据不一致

竞争条件

临界区:修改公共变量,不允许多进程执行

进入区->临界区->退出区->剩余区

解决方案满足性质:互斥,进步,有限等待

两种方法:抢占式和非抢占式内核

一个进程进入临界区需要获得锁,退出时需要释放锁

忙等待

自旋锁:检查锁是否释放,浪费CPU周期,优点是没有切换上下文

信号量初值为可用资源数量

使用资源wait()减少信号量计数

释放资源signal()增加信号量计数

死锁与饥饿

相互持有共享资源,无法释放

优先级反转:所有正在访问资源的进程获得访问它的更高优先级进程的优先级,直到用完资源恢复优先级

内存

每个进程单独内存空间

两个寄存器:基地址,界限地址

保护:两者相加在范围里面,防止用户修改操作系统数据结构

特权指令,在内核模式下执行,修改这两个寄存器存储的值

地址绑定

进程在执行时可以在磁盘和内存之间移动,在磁盘上等待形成输入队列

编译时:绝对代码

加载时:可重定位代码

执行时:大多数采用,从一个内存段移动到另一个内存段

逻辑地址:CPU生成的地址(虚拟地址)

物理地址:

通过MMU内存管理单元映射,基地址寄存器变为重定位寄存器,用户进程加载到内存前都要加上重定位寄存器里面的位置,用户程序不会看到真实的物理地址

动态加载

一个程序只有在调用时才会加载,所有程序都以可重定位加载格式保存在磁盘上,提高内存空间利用率

交换

内存->快速磁盘/备份存储

标准交换:换入换出内存进程,上下文切换时间高

移动系统不支持交换,用闪存,由于空间约束

移动系统的交互:空闲内存降低到一定阙值以下时,IOS不采用交换,而是要求应用程序自愿放弃分配的内存

连续内存分配

  • 为什么操作系统通常在低地址?

这取决于中断向量,一般中断向量位于低内存

内存保护:防止进程访问不属于它的内存,否则触发陷阱寻址错误

固定分区,每个分区只能由一个进程

可变分区,一大块可用内存,成为孔,内存有很多大小的孔

首次适应

最优适应

最差适应

内存碎片

存储被分成了大量小孔,总和能装下但是不连续,导致浪费

  • 空空闲块的哪段开始分配

解决外部碎片:紧缩。需要重定位是动态的,在运行时进行,但是开销比较昂贵

分段

允许进程的物理地址空间是非连续的

用户试图的内存管理方案,从程序员视角

逻辑地址:段名称和段偏移(二维,段号和偏移)

编译的时候自动分段

从二维地址到物理一维地址,通过段表实现,段表就是基址寄存器和界限寄存器值,通过段号映射到段表中

  • 段号怎么转换基地址?

分页

现在大多数操作系统使用

将物理内存分为固定大小的块(16kb),成为页帧;逻辑内存分为同样大小的快,称为页面

逻辑内存是连续的,但物理内存可能不是

CPU生成地址分成页码和页偏移,页码是页表的索引,页表和段表类似

页的大小为2的幂,地位表示页偏移,高位表示页码

不会产生外部碎片,但是可能有内存碎片,如果进程要求内存不是页的整数倍

内存中的帧要大于进程中的页

TLB转换表缓冲区

TLB命中:页面在TLB中

  • 共享页

共享公共代码,但是每个进程有自己的数据页

可重入代码:不能自我修改,所以多个进程可以执行相同代码

页表结构

  • 分层分页:减少内存所占页表空间,缺点但要多出一次访问

  • 哈希页表

  • 倒置页表:整个系统只有一个页表,每个条目保存一个地址空间标识符(PID)系统内每个虚拟地址<进程ID,页码,偏移>,每个地址<进程ID,页码>,减少了内存空间,但是增加查找空间

虚拟内存管理

允许执行进程不必完全处于内存

  • 为什么在许多情况下并不需要将整个程序置于内存中?

1。程序有处理异常错误条件的代码,这些代码几乎不执行

2.数组,链表和表等分配的内存量通常多于实际需要值

3.程序的某些选项和功能可能很少使用

虚拟内存将逻辑内存和物理内存分开

  • 请求调页:对于请求调页的虚拟内存,页面只有在程序执行期间被请求时才加载。调页程序会猜测在该进程被再次换出之前会用到哪些页,需要硬件支持来区分内存的页面和磁盘的页面,使用有效-无效位(不在逻辑内存里,或有效但只在磁盘上),这是系统试图改善几桶使用率和吞吐量

  • 缺页错误:访问标记为无效的页面

  • 页面置换:发生缺页错误,但是列表没有空闲帧,系统交换出一个进程释放所有帧并降低多道程序

  • 页面置换算法:FIFO,调出最旧的页面;最优页面置换,调出置换最长时间不会使用的页面,LRU最近最少使用算法,基于计数的页面置换

一些对于C++的思考 计算机系统层次结构

comments powered by Disqus