现代操作系统CS2310 (上)进程管理
操作系统基础
- 关于抽象abstaction
- (计算机组成的重要概念)
- 层次化抽象
- 将系统划分成多个层次,每个层次都对下层屏蔽了具体实现细节,只向上层提供了一组简单的接口,从而简化了系统的设计和维护。
- 对于计算机系统结构,可以抽象为硬件层、操作系统层、系统程序层、应用程序层、用户层。每个层次都对下层屏蔽了具体实现细节,只提供了一组简单的接口。
- 虚拟机 (Vitural machines)
- ==virtualization layer==
- vitural cpu & memory & devices
- vitural cpu & memory & devices
- ==virtualization layer==
- 什么是计算机操作系统 (Operating system / OS) ?
- 一种介于计算机用户与计算机应用间的“程序”
- 一个系统资源的分配者、其它程序的控制者
提供服务
- GUI
- program execution
- IO operations
- File-system manipulation
- communications
- error detection
- resource allocation
- accouting
- protection & security
系统调用 (System Call)
- OS提供的可编程接口
- 比如 fork() exit() wait() (unix) 等
- 比起使用系统调用,OS也向各类服务提供应用程序接口 ( Application program interface / Api) -> 可以视为一种对系统调用的封装和抽象
- 简单,易移植
- eg. Win32 API, POSIX API(UNIX, Linux, Mac OS), Java API(JVM)
- OS提供的可编程接口
Outline
- 进程管理
- 进程/线程/同步/死锁
- 内存管理
- 内存/虚拟内存
- 存储管理
- 文件系统/大容量存储结构/IO系统
- 分布式系统结构
- 进程管理
进/线程调度
并发 & 并行
- 并发 Concurrency
- 时分复用:多个任务在同一时段内共享资源,交替运行
- 并行 Parallelism (multi-core system)
- 多个任务在(通过多个处理单元)同一时刻同时执行,互相独立
- 多个任务在(通过多个处理单元)同一时刻同时执行,互相独立
进程 & 线程
进程 process | 线程 threads |
---|---|
独立存在 | 作为进程子集存在 |
携带更多状态信息 | 共享内存.系统资源 |
独立地址空间 | 共享地址空间 |
仅通过IPC通信交互 | 更多方式 |
上下文切换比较慢 | 同进程内切换速度很快 |
- 线程是进程内的执行单元,不能独立于进程存在,而只能在进程中产生。
- 每个线程都共享了进程的地址空间、文件描述符表和其他系统资源。
- 可以认为正因为线程之间共享了部分资源,如代码段、数据段和文件描述符表等,因此在线程之间进行切换时,不需要像进程切换那样复制和恢复整个地址空间,这使得线程切换速度更快。
- 同时,由于线程之间共享了相同的地址空间,因此线程之间的通信更加容易和高效。线程可以直接访问同一进程内的共享内存,无需通过进程间通信(IPC)的方式进行数据传递,这减少了通信的开销和复杂性。
用户线程 (user threads) & 核线程 (kernel threads)
- Many-to-one
多个用户线程对核隐藏,映射到一个内核级线程上,由内核级线程来执行
单个用户线程出现问题会导致同组线程都出问题;不能并行运行
- One-to-one
高并行支持
创建kernel thread有开销
Linux, windows NT/XP/2000, Solaris 9+
- Many-to-many
操作系统重构一定数量核线程
Windows NT with the ThreadFiber package - Two-level
在Many-to-many的基础上运行用户线程与核线程1对1绑定
进程 process
进程 process ( = job 作业)
- program becomes process when the exe file is loaded into memory
- 开始运行的程序被载入内存,成为进程(此处的“内存”、之后的“组分”与虚拟内存有关)
- 1 program can be several processes
- 一个程序可以产生多个进程
- program becomes process when the exe file is loaded into memory
一个进程的组成部分 conposition:
- 栈 stack
- …
- 堆 heap
- memroy dynamically allocated during run time
- 数据 data
- 文本 text
- programme code
PCB (Process control block)
- state
- num
- counter
- registers
- mem limits
- list of open files
- …
—> 包含进程的状态;控制;上下文切换;通信和同步;优先级管理信息
进程的状态 process state
- 一个新的进程的一生:
- 创建 (new)
- 就绪 (ready)
- 进程就绪,等待处理器分配资源
- 比如CPU正在忙着处理别的进程,可能新的进程就要等待
- 运行 (run)
- 执行指令
- 等待 (wait)
- 进程未就绪,等待事件的发生或完成
- 比如等待键盘输入字符
- 终止 (terminated)
- CPU的进程切换过程
- 保存当前进程的上下文(->PCB0)
- 切换到新进程的上下文(<-PCB1)
- …更新控制信息,开始执行新进程
- 结束执行新进程
- 保存新进程的上下文(->PCB1)
- 切换到原进程的上下文(<-PCB0)
- …
CPU调度 cpu scheduling
抢占 preemptive 和 非抢占 nonpreemptive
- 一个处于Run状态的进程是否可根据调度规则在运行过程中被其它进程中断?
- 能 -> 抢占式:允许中断
- 不能 -> 非抢占式:除非进程结束或者进入等待状态,即释放CPU资源,不允许另一个进程获取其CPU资源
什么是CPU调度
在进程的状态发生以下变化时,CPU可能作“调度”决策
- run -> wait
- run -> ready
- wait -> ready (I/O完成等event发生,等待资源分配)
- terminates
在1.4时做决策 -> 非抢占 (处理进程的等待和结束)
在2.3时做决策 -> 抢占 (处理新的ready进程)
调度器 Dispatcher
控制CPU
- 切换上下文
- 切换进程
- 切换用户/管理员权限
- 用户程序重启
调度延迟 Dispatch latency
time it takes for the dispatcher to stop one process and start another running.
调度算法
均为人为定义,可能会有版本差别。
可以将一切调度理解为队列的设计、出入队规则的设计。
一般不标注可抢占时,认为不可抢占。
先有四种基础决策。
FCFS (First-Come, First-Served)
- Convoy effect - short process behind long process
- 非常基础和朴素的安排方法
- 短进程不友好
SJF (P/NP)
Shortest-Job-First
- 先处理(预估的)总耗时最短的工作
- SJF(P)
- -> 先处理(预估的)剩余耗时最短的工作
- 小心地处理新进程和被抢占的进程的顺序
- SJF(P)
- 理论最优解
- 事实上,难点在于很难预测到底耗时多久( -> 预测方案)
会导致饥饿
- 等电梯。你住在高楼层。电梯总优先服务低楼层的人下楼。
- 低楼层总有人按电梯。
- 你永远等不到电梯。
- 类似地,优先级调度也会导致饥饿。
Example of SJF (NP)
Example of SJF (P)
优先级调度 PS (P/NP)
Priority Scheduling (高度类似SJF,仅更改判断条件)
- 先处理高优先级进程
- 注意同优先级进程的处理方式
时间片轮转调度 RR (P/NP)
Round-Robin Scheduling
在RR(quatum=q)算法下,每个进程获得一个时间片time slice,长度为q。
关于q
- 当取quatum为一个极大的值,相当于FCFS,对短进程不友好
- 当取quatum为一个极小的值,符合RR的意图,但是会消耗大量时间用于进程切换
- 需要一个较为合适的取值
Example of RR
关于饥饿
- FCFS 不会导致饥饿
- SJF, PS均会导致饥饿
- RR 可以有效避免饥饿
以下为混合决策,更加自定义化,请认真查看题目说明。
多级队列调度 Multilevel Queue Scheduling
multiques, eg. foreground & background
- each queue has own scheduling algo 每个队列都有独立的出队规则
- schedule between queues:
- eg1. fixed prority 规定出队优先级
- serve all from queue1, then 2
- may cause starvation
- eg2. time slice 轮转从两个队列调取进程
- each queue has a time slice
…
- each queue has a time slice
- eg1. fixed prority 规定出队优先级
多级反馈队列 Multilevel Feedback Queue Scheduling
a kind of ↑
- structure:
- queues 多少队列
- each queue’s sche algo 每个队列的出队规则
- method
- when to upgrade/demote jobs 任务的转移规则
- which queue a process will enter when that process needs service 进入时的初始队列
- classic example:
Q1(RR(8))->Q2(RR(16))->Q3(FCFS)
In Q1/Q2, not completed -> degrade and queue
If not used up and not degrade, requeue ( & get a new time slice)
- Example of MFQ
锁管理(进程同步)
进程同步 Process Synchronization
- producer - consumer problem
Critical Section Problem
- 临界资源:每个进程的访问互斥
(When one process is in critical section, no other processes may be in its critical section) - find protocol to solve 防止竞争的==协议==
- 临界资源:每个进程的访问互斥
Critical Section
do {
entry section // 资源保护开始
== critical section ==
exit section //资源保护结束
remainder section
} while (TRUE)To solve this
- Mutual Exclusion 互斥
- Progress
- work when OK and don’t postpone indefinitely
- Bounded Waiting 有限等待
- Sequential Access 顺序访问
如何实现同步
原语 / 原子操作 Atomic
- 硬件支持:atomic hardware instructions (原语)
- Atomic = non-interruptable 不可中断
Test&Set (TAS)
Either test memory word and set value: TestAndSet ()
Definition (由硬件实现)
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}Example (share bool Lock(False))
Solution:
do {
while ( TestAndSet ( &lock ))
; // do nothing
// critical section
lock = FALSE;
// remainder section
} while (TRUE)
->(Add bounded-waiting) :
每个进程在一段时间内只能获取一定次数的testandset操作资源,如果达到阈值,就等待一定时间后再尝试获取do {
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE;
// critical section
j = (i + 1) % n;
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
// remainder section
} while (TRUE);
Swap
安全地交换两个内存单元内的数据
- Example
do {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
// remainder section
} while (TRUE);
Mutex
- 一种轻量级的同步机制
- 实现两种基本操作:lock和unlock。
- 在lock()和unlock()之间的临界区域内同一时间只有一个进程可以访问共享资源,其他进程必须等待锁被释放才能进入临界区域。
|
Samophore
- 一种用于线程同步的机制,可以用于多线程编程中控制访问共享资源。
- 维护一个计数器和等待队列
Semaphore提供了两个主要的操作:wait(等待)和signal(发信号)。Semaphore的值为整数,初始值可以是任意的正整数,表示可用的资源数目。Semaphore的值只能在wait和signal操作中改变,且改变是原子的,所以可以避免竞态条件。
在C语言中,Semaphore是通过系统提供的sem_t类型来表示的。
- wait(等待):当一个线程想要使用Semaphore代表的共享资源时,它需要调用wait操作。
如果Semaphore的值为正数,则该线程可以使用该资源,同时Semaphore的值减1;
如果Semaphore的值为0,则该线程将被阻塞,直到有其他线程释放资源并增加Semaphore的值为止。
int sem_wait(sem_t *sem);
- signal(发信号):当一个线程使用完Semaphore代表的共享资源时,它需要调用signal操作。
这将增加Semaphore的值,并唤醒等待该Semaphore的线程,以便它们可以继续使用资源。
int sem_post(sem_t *sem);
Semaphore还有其他一些操作,例如初始化、销毁等。在使用Semaphore时,需要注意避免死锁等问题,通常需要仔细考虑线程的同步关系,避免资源竞争等问题。
死锁问题 Deadlock
Deadlock Characterization
- Mutual exclusion 资源互斥
同一时间仅有一个进程可以使用某资源 - Hold and wait
享有资源的进程等待其它资源 - No preemption
不允许抢占其它进程享有的资源 - Circular wait
互相等待形成环
哲学家吃饭都拿左边筷子
Resource-Allocation Graph algorithm
-> DEADLOCK AVOIDANCE
通过画资源分配图,检查是否存在死锁,以及确定导致死锁的进程和资源,进而解除死锁 (avoidance) ; 也可以用于避免死锁(在分配前检查是否可能导致死锁)
- 用资源分配图可以表示当前的资源和进程关系
常用于每个资源仅有1instance的情况(多个instance时,环路和死锁未必相关)
V:
- P: P1,P2… (process list)
- R: R1,R2… (resource list)
- E:
- request edges 请求边 ( process -> resource )
- assignment edges 分配边 ( resource -> process )
通过图判断死锁
- 无环 -> no deadlock
- 有环 ->
- 1 instance / resource type -> 死锁
- ->1 instance / … -> 死锁可能性
升级的资源分配图
- Each process must a priori claim maximum use
- claim edge 有向虚线:进程P可能请求资源R (P->R)
- request edge 实线(P->R)
- assignment edge 实线 (R->P)
只有当将需求边转换为分配边不会导致分配图中环的形成时,这个请求才会被允许。
Safe mode & safe sequence
Safe mode
在分配请求发生时检查是否这一请求是否使得系统处于安全模式(存在安全队列)以预防死锁
Defination:
系统中每个进程都能够按照它所需的顺序获得资源,执行完自己的任务并释放资源,而不会发生死锁。
- If Pi’s resource needs are not immediately available, then Pi can wait until all Pj have finished
- When all Pj are finished, Pi can obtain needed resources, execute, return allocated resources, and terminate
- When Pi terminates, Pi+1 can obtain its needed resources, and so on
- Otherwise, system is in unsafe state
安全模式 -> 无死锁
- 非安全模式 -> 有可能死锁
- starvation 饥饿 …
- Avoidance -> 确保系统不会进入非安全状态
Safe sequence 安全队列
- eg: available resource = 3
| |maximum needs|holds|needs|
|—|—|—|—|
|P0|10|5|5|
|P1|4|2|2|
|P2|9|2|7|
Avai | P1+ | P1- | P0+ | P0- | P2+ | P2- |
---|---|---|---|---|---|---|
3 | 1 | 5 | 0 | 10 | 3 | 12 |
P1 -> P0 -> P2
每一步寻找可运行的process,完成后释放process和它的所有资源。
如果找不到可运行的process,则出现unsafe state。
The banker’s algorithm
适用于资源有mutiple instances的情况
Defination
n = number of processes
m = number of resources types.Available: Vector of length m.
If available\[j] = k, there are k instances of resource type Rj available
- Max: n x m matrix.
If Max\[i,j] = k, then process Pi may request at most k instances of resource type Rj
- Allocation: n x m matrix.
If Allocation\[i,j] = k then Pi is currently allocated k instances of Rj
Need: n x m matrix.
If Need\[i,j] = k, then Pi may need k more instances of Rj to complete its task Need\[i,j] = Max\[i,j] – Allocation\[i,j]**
The algorithm
- work := available, finish[i] = false
- find i that
- finish[i] = false
- need[i] <= work
- if i = -1, go to 4
- work = work + allocation[i], finish[i] = true, go to 2
- if finish[i] = true for all i -> ok, else !ok
Simulation
+P1->[2,1,0]->-P1->[5,3,2]
+P3->[5,2,1]->-P3->[7,4,3]
+P0->[0,0,0]->-P0->[7,5,3]
+P2->[1,5,3]->-P2->[10,5,5]
+P4->[12,2,4]->-P4->[10,5,7]
Sum up: deadlock handling
PREVENTION
-> restrain the ways request can be made
shown in [deadlock characterization]
AVOIDANCE
入职检查
Whenever a process requests a resource, the request is granted only if the allocation leaves the system in a safe state.
Help system to add priori info
- Prepare for checking: each process declare max of resources needed
- Dynamically check if there’ll be circular-wait condition
- be defined by available/allocated resourvces, max demands of processes
- safe state checking (bank algo/…) ; circle check
DETECTION
similar to avoidance
RECOVERY
precess termination 进程终结
- 一次终结所有/逐个终结直至死锁解除
resource preemption 资源抢占
- 允许从一个或多个死锁进程中抢占资源
- selecting a victim / rollback 回滚
- 可能导致饥饿