处理机管理
- 程序:指令序列(存放在程序段、数据段)
- 进程实体(静态的):
- 进程控制块PCB:各种进程信息及在内存中的位置(指针),是进程存在的唯一标志。操作系统提供PCB来管理进程。
- 程序段
- 数据段
- 进程是一个动态的过程,是进程实体的运行过程,是系统进行资源分配和调度的独立单位。
- 进程的三种基本状态:
- 运行态:占有CPU,并在上面运行
- 就绪态:
- 阻塞态:等待某一事件而暂时不能运行
- 创建态
- 终止态
- 进程状态的转换:(事件占有处理机才能做出主动行为)
- 进程的控制:实现进程状态的转换,即上图的绿色箭头。进程状态的转换要修改PCB内容和相应队列。
- 为了防止状态PSW与队列信息不一致——用原语实现进程控制(不可中断操作,即原子操作)。原语采用关、开中断指令(核心态下单特权指令)实现。
- 创建原语和撤销原语
- 进程的阻塞和唤醒原语(成对使用)
- 切换原语
- 进程通信——进程之间信息交换。各进程拥有的内存地址空间相互独立,为保证安全,一个进程不能直接访问另一个进程的地址空间。
- 进程通信方法:
- 共享存储:”共享空间”、访问时互斥、
- 基于数据结构
- 基于存储区
- 消息传递:格式化的消息(message)、发送/接受消息原语
- 直接通信
- 间接(信箱)通信(eg:电子邮件系统)
- 管道通信:pipe文件、缓冲区、半双工、互斥、未写满不能读、未读空不能写。
- 共享存储:”共享空间”、访问时互斥、
- 线程(“轻量级进程”程序执行流的最小单位)——增加并发度
- 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位
- 线程间并发不需要切换运行环境,系统开销小。同一进程间的不同线程共享进程资源
- 线程实现方式:
- 用户级线程
- 内核级线程——才是处理机分配的单位
- 多线程模型(用户—内核):
- 多对一
- 一对一
- 多对多
- 处理机调度:
- 调度的三个层次:
- 高级(作业)调度:面向作业
- 中级(内存)调度:挂起状态(暂时调到外存等待)、PCB常驻内存、面向进程
- 低级(进程)调度
- 进程调度的方式:剥夺(只允许进程主动放弃处理机)/非剥夺(可优先处理更紧急的进程)
- 调度的三个层次:
- 周转时间:=作业完成时间-提交时间
- 等待时间:=周转时间-运行时间(-I/O操作时间)
- 带权周转时间:=周转时间/作业实际运行时间、越小越好
- 作业后备队列(在外存中)
- 调度算法:(以下三种适用于早期的批处理系统)
- 先来先服务FCFS:“公平”、先到达后备队列、非抢占式、对短作业(进程)来说用户体验不好、不会导致饥饿
- 短作业优先SJF:追求最少的平均等待时间、默认是非抢占式的(有抢占式的版本SRTN)、会导致饥饿
- 高响应比优先HRRN:综合考虑作业/进程的等待时间和要求服务的时间(即运行时间)、响应比(=(等待时间+要求服务的时间)/ 要求服务的时间)、非抢占式的算法、不会导致饥饿
- 调度算法:(以下三种适用于交互式系统)
- 时间片轮转调度算法RR:根据到达就绪队列的时间顺序轮流执行一个时间片、用于进程调度、抢占式算法、注意时间与进程切换时间的比例、不会导致饥饿
- 优先级调度算法:设置优先级、抢占式和非抢占式都要、静态/动态优先级、有可能导致饥饿
- 多级反馈队列调度算法:对其他调度算法的折中权衡、用于进程调度、抢占式的算法、相对公平、会导致饥饿
- 进程同步:直接制约关系,需要协调进程的工作次序
- 进程互斥:临界资源、临界区(访问临界资源的那段代码)、空闲让进、忙则等待、有限等待、让权等待
- 进程互斥的软件实现方法:
- 单标志法:每个进程进入临界区的权限只能被另一个进程赋予、违背了空闲让进原则、turn
- 双标志先检查:标记各进程想进入临界区的意愿、违反忙则等待原则、flag[2]
- 双标志后检查:先占坑、违背了空闲让进和有限等待原则flag[2]
- Peterson算法:turn和flag[2]、未遵循让权等待原则
- 中断屏蔽方法:利用“开/关中断指令”实现(运行在内核态),不适用于多处理机、用户进程,适用于操作系统内核进程。
- TestAndSetLock(TSL)指令:一气呵成、硬件实现、会导致忙等
- Swap指令(XCHG指令):硬件实现、一气呵成
- 信号量机制:(——实现进程互斥、同步)、一对原语(wait(S)相当于进入区,占用资源;signal(S)相当于退出区,释放资源)(P、V)
- 整型信号量:只能进行初始化、P、V操作、检查&上锁一气呵成、但不满足“让权等待”&会导致忙等、
- 记录型信号量:为了解决忙等问题、增加了等待队列、当资源数不够时使用block原语使进程从运行态切换到阻塞态、释放资源后若还有别的进程也在等待这个资源则使用wakeup原语唤醒等待队列中的一个进程(阻塞态->就绪态)、遵循了“让权等待”原则&不会出现忙等
- 信号量机制实现1-进程互斥:划定临界区、对不同的临界资源设置不同的互斥信号量(mutex)、P、V操作成对出现
- 信号量机制实现2-进程同步:有序、在前操作之后执行V且在后操作之前执行P
- 信号量机制实现3-前驱关系(更复杂的同步问题):(前驱图)
- 生产者-消费者问题:需要三对信号量、实现互斥的P操作一定要在实现同步的p操作之后,而两个V操作的顺序可以互换。
- 多生产者-多消费者问题:注意应该从“事件”的角度分析前后顺序
- 吸烟者问题:轮流使各个吸烟者吸烟
- 读者-写者问题:允许读者同时读,不允许读者读的时候写者写、也不允许写者同时写。
-
重点:对访问count变量的操作加互斥锁
-
- 哲学家进餐问题:
- 管程:(——更方便地实现进程的同步和互斥,应用了封装的思想)由以下部分构成:
- 局部于管程的数据结构说明
- 对该数据结构进行操作的一组过程
- 设置初始值的语句
- 管程的名字
- 基本特征:(注:过程=函数)
- 局部于管程的数据只能被局部于管程的过程所访问。
- 一个进程只有通过调用管程内的过程(或者特定的“入口/接口”)才能进入管程访问共享数据。
- 每次进允许一个进程在管程内执行某个内部过程(实现了类似于互斥的功能)
- JAVA中类似于管程的机制:关键字synchronized,如果用该关键字来描述一个函数,那么这个函数同一时间段内只能被一个线程调用。
- 死锁(deadlock):各进程互相等待对方手里的资源,导致各进程都堵塞,无法向前推进的现象。(循环等待“对方”手里的资源)、两个或两个以上、发生死锁的进程一定处于阻塞态、分配操作系统资源不合理
- 死锁产生的必要条件:互斥、不可剥夺(抢占)、请求和保持条件、循环等待条件(循环等待链)
- 预防死锁、避免死锁、死锁的检测和解除
- 预防死锁:破坏死锁产生的四个必要条件(之一)、SPOOLing技术破坏互斥条件(互斥改为共享)、
- 避免死锁:银行家算法、所谓安全序列——系统按这种序列分配资源则每个进程都能顺利完成——系统处于安全状态(不会发生死锁)、因此在分配资源之前预先判断这次分配是否会导致系统进入不安全状态——银行家算法的核心思想
- 银行家算法:单维的数字扩展为多维的向量
- 死锁的检测和解除:——数据结构:资源分配图
- 检测:消除资源分配图中所有的边-可完全简化-不会发生死锁
- 解除