进程可看做正在执行的程序,执行时需要资源。
进程是多大数系统中的工作单元。
os负责进行管理:创建与删除,进程调度,进程同步机制,通信机制与死锁处理
- 进程
- CPU调度
- 进程同步
- 死锁
进程
- 进程概念
- 进程调度
- 进程操作
- 进程通信
- 线程
进程概念
进程:具有一定独立功能的程序关于某个数据集合的一次运行活动,是系统进行资源分配和调度的独立单位,包括pc,stack,data section(数据)
是一个运行中的程序。
进程实体由程序,数据和进程控制块3部分组成的。
进程状态转化图进程状态转化图进程状态转化图
进程调度队列
job queue:all process(保存了系统中所有进程)
ready queue :wait for cpu
device queue :wait for io
process migration between the queues
long term scheduler :将进程放入ready queue
short term scheduler:将进程交给cpu执行
medium term scheduler:颠簸,将进程移除内存
上下文切换:保存上一个进程的PCB,装入下一个进程的PCB。需要硬件支持(切换时间与硬件支持程度密切相关)
进程操作
进程操作包括:创建,执行,终止。
进程由其父进程创建,故进程逻辑上是树状结构。
创建进程
- 分配PCB(包括pid)
- 分配资源 (COW,copy on write)
- 初始化PCB
- 将进程放入ready queue
fork(复制父进程) ,父进程返回子进程pid,子进程返回0
exec(导入新程序)
wait
进程间通信 IPC
协作进程间需要进行通信。
进程间通信的方法
- 共享内存 :快、冲突
- 消息传递 :通过os传递,数量少
- pipe :共享文件
IPC最好有消息传递系统提供。(允许进程间通信而不需要共享数据)
消息传递系统包括
- 直接通信 :连接自动建立,只能有两个进程,两个进程之间只能有一个连接,
- 间接通信:通过邮箱发送。共享邮箱即可建立连接,两个进程间可有多个邮箱
线程
进程太大,创建太贵,切换不方便,且通信需要通过os。
将进程中分为资源型和调度型,调度型组成线程,资源型共享。
线程是CPU执行的基本单元,由线程id,stack,pc,寄存器组成,与同属于一个进程的其他线程共享代码,数据,文件等其他操作系统资源。
常见的多线程模型(用于:内核)
- 1对1
- 多对1
- 多对多
CPU调度
cpu调度是多道程序操作系统的基础。
进程从cpu burst 开始,结束于cpu burst。
cpu调度分为抢占式和非抢占式。抢占式是当有新的进程加入到ready queue中需要考虑是否进行调度。
分配程序
- 切换上下文
- 转化到用户模式
- 移动pc到合适的位置
调度准则
- cpu使用率
- 吞吐量
- 周转时间:进程从提交到结束
- 等待时间:进程在ready queue中的时间。
- 相应时间:从提交到第一次执行
调度算法
- FCFS
- 存在护航效果:所有进程都在等一个执行时间较长的进程。
- SJF
- 存在抢占式和非抢占式,是优先级的一种。
- 抢占式:当有新的进程加入后,需要考虑是否短于当前执行的进程。又称为最短剩余时间优先调度。
- 是最佳的。长期调度中可以用最大极限来代替实际时间,故常用该法。
- 优先级调度
- 一般数字越小,优先级越高
- 可能出现饥饿(无穷阻塞)的情况,解决办法:老化。
- 轮转法调度 RR
- 浪费时间在上下文切换上
- 时间片的选择也很重要,太大就是FCFS,太短则上线爱问切换成本太高。
- 多级队列调度。进程属于一个队列,不可更改
- 多级反馈队列调度。可换队列
进程同步
竞争条件:多个进程并发访问和操作同一个数据,且结果与访问顺序有关。
为了解决竞争条件,需要进行同步。
临界区:考虑一个有n个进程的系统,每个进程有一个代码段称为临界区,在该区中进程可能改变共同变量、更新一个表、写一个文件等。这种系统的重要特征是当一个进程在临界区内执行,没有其他进程被允许在临界区内执行。
临界区的解决方案必须满足三个条件
- 互斥
- 每次只能有一个进入临界区
- 前进
- 若临界区没有进程,且一个进程想进去,则能进去
- 如果有其他进程想进入临界区,那刚从临界区出来的进程不能立刻再进入临界区
- 有限等待
- 不会永远等待
进程进入临界区之前,需要在entry section(进入区)申请进入,结束临界区的执行后,需要进入exit section(退出区)
entry section
critical section
exit section
临界区解决方案
- Peterson’s Solution
是两个进程的临界区解决方案。
// 进程i
do {
flag [i] = true;
turn = j;
while (flag [j] and turn == j) ;
critical section
flag [i] = false;
remainder section
} while (1);
- 硬件同步
通过原子操作TestAndSet ,Swap实现同步。
boolean TestAndSet (boolean *target){
boolean rv = *target;
*target = TRUE;
return rv:
}
// soulution
while (true) {
while ( TestAndSet (&lock )) ; // do nothing
// critical section
lock = FALSE;
// remainder section
}
void Swap (boolean *a, boolean *b){
boolean temp = *a;
*a = *b;
*b = temp:
}
//Solution:
while (true) {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
// remainder section
}
- 信号量
// int s ; can only be accessed via two indivisble (atomic)
//p()
wait(s){
while(s<=0)
;
s--;
}
// v()
signal(s){
s++;
}
semaphore mutex ;// initially mutex = 1;
// for pi
wait(mutex);
ceitical section
signal(mutex);
死锁:组内的每个进程都等待一个事件,而该事件只可能由组内的另一个进程产生。
经典同步问题
- 有限缓存/生产者,消费者问题
// init
empty = N;
mutex = 1;
full = 0;
生产者
while(true){
wait(empty);
wait(mutex);
// add item
signal(mutex);
signal(full);
}
消费者
while(true){
wait(full);
wait(mutex);
// remove
signal(mutex);
signal(full);
}
- 读者写者问题
分为
- 第一读者写者问题:读者优先(若一个读者获得允许使用共享数据库,且有一个写者进程在等待,则其他读者进程不需要等待。)
- 第二读者写者问题:写者优先(一旦写者就绪,写者会尽可能快获得共享数据库。)
wrt = 1;
mutex = 1;
int counter = 0;
//writer
while(true){
wait(wrt);
// writing
signal(wrt);
}
//reader
while(true){
wait(mutex);
count++;
if(count == 1)
signal(wrt);
siganl(mutex);
// reading
wait(mutex);
count --;
if(count == 0)
siganl(wrt);
siganle(mutex);
}
monitors 管程
高级同步原语
一次只有一个线程执行,不需要显示编写同步,但需要写一些条件。
死锁
死锁:当一组进程的每个进程都在等待一个事件,而这一事件只能有这一组进程的另一个进程所引起,那么这组进程就处于死锁状态。
系统模型
Resource types R1, R2, . . ., Rm
Each resource type Ri has Wi instances.
Each process utilizes a resource as follows:
- request
- use
- Release
特征
死锁条件/特征
- 互斥:至少有一个资源必须处于非共享模式;即一次只有一个进程使用。如果另一资源申请该资源,那么申请进程必须延迟直到该资源释放为止。
- 占有并等待:一个进程必须占有至少一个资源,并等待另一资源,而该资源被其他进程所占。
- 非抢占:只在进程完成其任务之后,才会释放其资源。
- 循环等待:
资源分配图
- 如果图没有环,那么系统就没有进程死锁。如果图有环,那么可能存在死锁。
- 如果每个资源类型刚好有一个实例,那么有环就意味着死锁,环是死锁的充分必要条件。
- 如果每个资源类型有多个实例,那么有环并不意味着出现死锁。环是死锁的必要非充分条件。
死锁处理
死锁处理包括
- Deadlock Prevention
- Deadlock Avoidance
- Deadlock Detection
- Recovery from Deadlock
- Deadlock Prevention
从四个条件入手,解决死锁。
- 互斥
- 共享资源不互斥
- 非共享资源互斥
- hold and wait
- 进程请求资源时,不能持有其他资源
- 资源低效利用,饿死
- 进程请求资源时,不能持有其他资源
- 非抢占
- 允许抢占,使用范围不广
- 循环等待
- 有序资源分配:对资源排序,并要求进程按递增序列请求资源
互斥和非抢占式资源本身的特性,不易改变。
- Deadlock Avoidance
通过增加附加信息来实现避免死锁
- 已分配的资源
- 可获得的资源
- 进程最大资源需求数量
安全状态
- 如果系统能按某个顺序为每个进程分配资源并能够避免死锁,那么系统状态就是安全的。
系统是安全的,如果存在一个安全序列。
一个序列是安全(p1,p2,...,pnp_1,p_2,...,p_np1,p2,...,pn):对于每个pip_ipi,它所请求的资源能够被 当前可获得的资源和 pjp_jpj持有的资源ruc 所满足(j<i)
安全一定不死锁,不安全不一定死锁,死锁一定不安全。要避免系统进入不安全状态。
死锁避免算法
- 资源分配图:资源是单实例
- 虚线表示请求,有向图,没有环是
- 银行家算法:资源时多实例
银行家算法
设n个进程,m种资源。
available:各种资源可获得的数量
max:每个进程对每种资源的最大请求数量
allocation :每个进程目前每种资源获得的数量
need :每个进程对每种资源还需的数量
need = max - allocation
// Safety Algorithm
1. Let Work and Finish be vectors of length m and n, respectively. Initialize:
Work = Available
Finish [i] = false for i - 1,2, …, n.
2. Find an i such that both:
(a) Finish [i] = false
(b) Needi <= Work
If no such i exists, go to step 4.
3. Work = Work + Allocation[i];
Finish[i] = true;
go to step 2.
4. If Finish [i] is true for all i, then the system is in a safe state.
// Resource-Request Algorithm for Process Pi
Request = request vector for process Pi.
If Request[i][j] = k, then process Pi wants k instances of resource type Rj.
5. If Requesti <= Needi go to step 2.
Otherwise, raise error condition.
6. If Requesti <= Available, go to step 3.
Otherwise Pi must wait.
7. Have the system pretend to have allocated requested resources to Pi by modifying the state as follows:
Available = Available - Requesti;
Allocationi = Allocationi + Requesti;
Needi = Needi – Requesti;
If safe , the resources are allocated to Pi.
If unsafe ,Pi must wait, and the old resource-allocation state is restored
- Deadlock Detection
如果不进行死锁预防和死锁避免,则可能出现死锁。
出现死锁,需要
- 检测死锁算法
- 恢复算法
检测死锁