文章目录
操作系统的运行机制和体系结构
运行机制:
操作系统的内核:
内核是计算机上配置的底层软件,是操作系统最基本、最核心的部分。
实现操作系统内核功能的那些程序就是内核程序。
操作系统的体系结构:大内核、微内核
中断和异常
中断机制的诞生解决程序串行的问题。
中断的概念和作用:
由于操作系统的管理工作(如进程切换、分配I/O设备等)需要使用特权指令,因此CPU要从用户态转为核心态(使用中断,中断是用户态切换到核心态的唯一途径)
中断的分类
另一种分类:
外中断的处理过程
步骤:
系统调用
操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。其中,程序接口由一组系统调用组成。
系统调用是操作系统提供给应用程序(程序员/编程人员)使用的接口。
在用户程序中,凡是与资源有关的操作(存储分配、I/O操作),都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成。
可以保证系统的稳定性和安全性,防止用户进行非法操作。
系统调用与库函数的区别:
系统调用的过程:
int指令(陷入指令),使其进入核心态
陷入指令是在用户态执行的,执行后立即引发一个内中断,从而CPU进入核心态。
系统调用会使处理器从用户态进入核心态。
进程
程序:是一个指令序列
早期计算机只支持单道程序;
引入多道程序技术;
组成:
进程实体(一般也称为进程):PCB、程序段、数据段三部分构成。
进程:是进程实体的运行过程。是系统进行资源分配和调度的一个独立单位。
**PCB是进程存在的唯一标志。**用来描述进程的各种信息。
进程:是一个程序的执行过程,具有“动态性”。
进程标识符PID:
组织方式:
链接方式:
索引方式:
特征:
动态性、并发性、独立性、异步性、结构性。
状态:
运行态,就绪态,阻塞态;
创建态,终止态;
简易理解:
状态的转换:
挂起态和七状态模型:
进程控制
用“原语”实现;就是要实现进程状态的转换。
原语是一种特殊的程序。
原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断。
关/开中断指令是只允许在核心态下的特权指令。
相关的原语:
原语都会做:1、更新PCB中的信息 2、将PCB插入合适的队列 3、分配/回收资源
创建原语、终止原语、阻塞原语、唤醒原语、切换原语
进程通信
共享存储:
管道通信:
采用半双工通信
要实现双向通信需要有两个管道;
管道只有在写满时,才能被读;只有在空时才能被写;
消息传递:
进程间的数据交换以格式化的消息(Message)为单位。进程通过操作系统提供的“发送消息/接收消息"两个原语进行数据交换。
线程
线程:是一个基本的CPU执行单元,也是程序执行流的最小单位。(轻量级进程)
提升了系统的并度,减少了系统开销;
属性:
实现方式:
用户级线程
用户能够看到线程,操作系统看到的只是进程。
内核级线程:
在同时支持用户级线程和内核级线程的系统中,可采用二者组合的方式:
内核级线程才是处理机分配的单位。
多线程模型
在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射道几个内核级线程的问题引出了"多线程模型"
多对一模型:
一对一模型:
多对多模型:
注:
进程同步、互斥
回顾:
-
进程具有异步性,指各并发执行的进程以各自独立的、不可预知的速度向前推进。
-
进程同步就是为了解决进程异步性的问题。
同步(直接制约关系):指为完成某种任务而建立的两个或多个进程,因为需要在某些位置上协调它们的工作次序而产生的制约关系。(直接制约关系源于它们之间的相互合作)
建议理解:同步就是让进程有工作次序。
进程互斥(间接制约关系):
指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。
实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则:
1、空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
2、忙则等待:当已有进程进入临界区时,其他试图进入临界区的几次呢必须等待。
3、有限等待:对请求访问的进程,应保证能在有限时间内进入临界区(防止饥饿)
4、让权等待:进程不能进入临界区时,应立即释放处理机
进程互斥的软件实现方法
单标志法
思想:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。
只能P0->P1->P0->P1轮流访问。
存在问题:违背了“空闲让进”原则
双标志先检测法
思想:
先“检查“后上锁。
双标志后检测法:
先”上锁“后”检查“
违背了”空闲让进“和”有限等待“原则,会产生”饥饿“现象。
Peterson算法
”孔融让梨“,主动让对方先使用临界区。
进程互斥的硬件实现方法
中断屏蔽方法:
利用”开/关中断指令“实现
优点:简单高校
缺点:不适用于多处理机;只适用于操作系统内核进程,不适合于用户进程(因为中断指令只能运行内核态)
TestAndSet指令
优点:实现简单;适用于多处理机环境
缺点:不满足”让权等待“原则。
Swap指令
优点:简单
缺点:不满足"让权等待"原则。
信号量机制
用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。
信号量是一个变量(可以是整数,或者是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量。
整型信号量
存在问题:不满足”让权等待“原则,会发生”忙等“。
记录型信号量
signal原语中,S.value<=0说明还有进程正在等待分配资源(有资源处于等待队列),因为wait是先执行了S.value–后进入挂起状态。有进程等待所以需要执行wekeup原语。
遵循了”让权等待“原则。(进程自我阻塞就是主动放弃处理机)
注:考试中P(S),V(S)操作默认S为记录型信号量
实现进程互斥
互斥信号量mutex
信号量的声明可以自己定义。
要使用不同的临界资源就定义新的互斥信号量
实现进程同步
分析:
实现前驱关系
要求代码按如下前驱图顺序去执行:
类似于同步操作。
生产者-消费者问题
分析思路:
semaphore mutex=1;//互斥信号量,实现对缓冲区的互斥访问
semaphore empty=n;//同步信号量,表示空闲缓冲区的数量
semaphore full=0;//同步信号量,表示产品的数量,也即非空缓冲区的数量
//生产者
producer(){
while(1)
{
生产一个产品;
P(empty);
P(mutex);
把产品放入缓冲区;
V(mutex);
V(full);
}
}
//消费者
consumer(){
while(1)
{
P(full):
P(mutex);
从缓冲区取走一个产品;
V(mutex);
V(empty);
使用产品;
}
}
注:
-
实现互斥是在同一进程中进行一对PV操作;
-
实现两进程的同步关系,是在其中一个进程中执行P,另一进程中执行V
-
两个相邻的P操作不能互换,实现互斥的P操作一定要在实现同步的P操作之后。
-
V操作不会导致进程阻塞,两个相邻V操作可以互换
-
非临界区代码可以放入临界区,但是会降低并发度
多生产者-多消费者问题
代码实现:
吸烟者问题
代码实现:
读者-写者问题
分析题目:
解决:设置互斥变量,使操作P(rw)和count++一气呵成
但还是存在问题;解决:加一个互斥信号量。
这样执行顺序会按序执行;
总体代码:
“写优先”类似于先来先服务,没用真正的写优先
哲学家进餐问题
如何防止死锁:
实现代码:(另一种方式)
哲学家问题关键在于解决死锁;
管程
管程的定义:
即把过程封装起来。
基本特征:
用管程解决生产者消费者问题:
(以下就是管程ProducerConsumer的写法,各有不同)
总结: