目录
2.1进程与线程
2.1.1进程的概念和特征
(1)进程的概念:进程是进程实体的执行过程,是系统进行资源分配和调度的一个独立单位。
(2)进程实体组成:程序段、相关数据段、PCB。
(3)进程的特征:
(1)动态性:进程是程序的一次执行,有着创建、活动、暂停、终止等过程。动态性是进程最基本的特征。
(2)并发性:多个进程同时存在于内存中,能在一段时间内同时运行。
(3)独立性:进程是一个能独立运行、独立获得资源和独立接受调度的基本单位。
(4)异步性:进程具有执行的异步性。
(5)结构性:进程实体由:程序段、数据段和进程控制块三部分组成。
(4)引入进程的目的:
为了使程序能与其他进程的程序并发执行,以提高资源利用率。
2.1.2进程的状态与转换
(1)进程的五状态转换
(2)进程的七状态转换
2.1.3进程的通信
进行通信定义:进程通信是指进程之间的信息交换。PV操作是低级通信方式。高级通信如下
(1)共享存储(需要使用同步互斥工具,例如(P操作、V操作))
共享存储分为: 低级方式的共享是基于数据结构的共享;
高级方式的共享是基于存储区的共享。
(2)消息传递
(1)直接通信方式:直接把消息挂在接受进程的消息队列。
(2)间接通信方式(例如信箱)
(3)管道通信(半双工通信)
定义:所谓管道,是指连接一个读进程和一个写进程以实现它们之间的通信的共享文件,又名pipe文件。
2.1.4线程概念和多线程模型
(1)引入进程的目的:
为了更好地使多道程序并发执行,提高资源利用率和系统吞吐量。
(2)引入线程的目的:
为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
(3)多线程模型
1.多对一模型
优点:线程管理是在用户空间进行的,因而效率高
缺点:一个线程在使用内核服务时阻塞,整个进程都会被阻塞;
多个进程不能并行地运行在多处理机上。
2.一对一模型
优点:当一个线程阻塞后,允许另一个线程继续执行,并发能力强。
缺点:每创建一个用户级线程就需要创建一个内核级线程与之对应,这样创建线程的开销较大,会影响整个应用程序的性能。
3.多对多模型(用户级线程数>=内核级线程数)
优点:集多对一和一对一的优点
2.2处理机的调度
2.2.1调度的概念
(1)调度:从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程并发地执行。
(2)调度的层次
(1)作业调度(高级调度):内存和辅存之间的调度。每个作业只调入一次,调出一次
(2)内存调度(中级调度):将不能运行的进程调入外存等待,也称为挂起
(3)进程调度(低级调度):从就绪队列中选取一个进程,将处理机分配给它。
2.2.2进程调度方式
(1)非剥夺调度方式
优点:实现简单,系统开销小,适用于大多数的批处理系统
缺点:不能用于分时系统和大多数的实时系统
(2)剥夺调度方式
优点:对提高系统吞吐率和响应效率都有明显的好处。
2.2.3调度的基本准则
(1)CPU利用率
(2)系统吞吐量:单位时间内CPU完成作业的数量。
(3)周转时间 = 作业完成时间 - 作业提交时间
带权周转时间 = 作业周转时间 / 作业实际运行时间
(4)等待时间:等处理机状态的时间之和。
(5)响应时间:从用户提交请求到系统首次响应所用的时间。
2.2.4典型的调度算法
(1)先来先服务调度算法(FCFS)
特点:算法简单,但效率低;对长作业有利但对短作业不利;有利于CPU繁忙行作业,不利于I/O繁忙行作业。
(2)短作业优先(SJF)调度算法
特点:对长作业不利,可能会出现“饥饿”。SJF平均等待时间、平均周转时间最少。
(3)优先级调度算法(可能会“饥饿”)
系统进程>用户进程
交互型进程>非交互型进程
I/O型进程 > 计算型进程
(4)高响应比优先调度算法(HRRN)
响应比Rp = (等待时间+要求服务的时间)/ 要求服务的时间
特点:克服了饥饿状态,兼顾了长作业。
(5)时间片轮转调度算法(RR)
特点:主要用于分时系统。时间片太大太小都不合适,时间片太大退化成FCFS调度算法,时间片太小加大了进程切换导致的系统开销;
(6)多级反馈队列调度算法
多级反馈队列 = 时间片轮转调度算法 + 优先级调度算法
2.3进程同步
2.3.1进程同步的基本概念
(1)临界资源:仅允许一个进程使用的资源称为临界资源。
(2)临界区:访问临界资源的那段代码称为临界区。
(3)同步:直接制约关系。(先V后P)
(4)互斥:间接制约关系(先P后V)
(5)为禁止两个进程同时进入临界区,应该遵循以下准则:
(1)空闲让进
(2)忙则等待
(3)有限等待:对请求访问的进程,应保证在有限时间内进入临界区。
(4)让权等待:当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。
2.3.2实现临界区互斥访问的基本方法
(一)软件实现方法
(1)单标志法(违背了“空闲让进”)
P0进程: p1进程:
while(turn != 0); while(turn != 1);
critical section; critical section;
turn = 1; turn = 0;
remainder section; remainder section;
(2)双标志法先检查(违背了“忙则等待”)
P0进程: p1进程:
while(flag[j]); while(flag[i]);
flag[i] = TRUE; flag[j] = TRUE;
critical section; critical section;
flag[i] = FALSE; flag[j] = FALSE;
remainder section; remainder section;
(3)双标志法后检查(违背了“空闲让进” “有限等待”)
P0进程: p1进程:
flag[i] = TRUE; flag[j] = TRUE;
while(flag[j]); while(flag[i]);
critical section; critical section;
flag[i] = FALSE; flag[j] = FALSE;
remainder section; remainder section;
(4)Peterson算法(违背“让权等待”)
P0进程: p1进程:
flag[i] = TRUE; turn = j; flag[j] = TRUE; turn = i;
while(flag[j] && turn == j); while(flag[i] && turn == i);
critical section; critical section;
flag[i] = FALSE; flag[j] = FALSE;
remainder section; remainder section;
(二)硬件实现方法
(1)中断屏蔽方法
(2)硬件指令方法
TestAndSet指令
Swap指令
2.3.3信号量
(1)整形信号量(初始化、P操作、V操作)
(2)记录性信号量
2.3.4管程(进程同步工具)
(1)定义:代表共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序,称为管程
(2)管程组成(类似于“类”)
(1)管程(monitor)的名称
(2)局部于管程内部的共享结构数据说明
(3)对该数据结构进行操作的一组过程
(4)对局部于管程内部的共享数据设置初始值的语句
2.3.5经典的同步问题
(1)生产者-消费者问题(同步互斥问题)
semaphore mutex = 1; //临界区互斥访问
semaphore empty = n; //空闲缓冲区
semaphore full = 0; //缓冲区初始为空
producer(){ //生产者进程
produce an item in nextp;
p(empty);
p(mutex);
add nextp to buffer;
v(mutex);
v(full);
}
consumer(){ //消费者进程
while(1){
p(full);
p(mutex);
remove an item from buffer;
v(mutex);
v(empty);
consume the item;
}
}
(2)读者-写者问题
问题描述:有读者和写者两组并发进程,共享一个文件。
要求:允许多个读者可以同时对文件执行读操作;只允许一个写者往文件写信息;任一写者在完成写操作之前不允许其他读者或写者工作; 写者执行写操作之前,应让已有的写者和读者全部退出
int count = 0; //用于记录当前的读者数量
semaphore mutex = 1; //保护更新count时的互斥
semaphore rw = 1; //互斥访问文件
writer(){ //写者进程
while(1){
P(rw);
writing;
V(rw);
}
}
reader(){ //读者进程
while(1){
P(mutex);
if(count == 0){
P(rw);
}
count++;
V(mutex);
reading;
P(mutex);
count--;
if(count == 0)
V(rw);
V(mutex);
}
}
(3)哲学家进餐问题
问题描述:5个哲学家围成一桌,五根筷子。
semaphore chopstick[5] = {1, 1, 1, 1, 1}; //五根筷子
semaphore mutex = 1; //取筷子信号量
Pi(){
do{
P(mutex);
P(chopstick[ i ]);
P(chopstick[ (i+1)%5 ]);
V(mutex);
eat;
V(chopstick[ (i+1)%5 ]);
V(chopstick[ i ]);
think;
}while(1);
}
(4)吸烟者问题
问题描述:假设三个抽烟者进程和一个供应者进程。每个抽烟者不停的卷烟并抽掉它,但要卷一支烟,需要三种材料 :烟草、纸和胶水。三个抽烟者中,第一个只拥有烟草,第二个只拥有纸,第三个只拥有胶水。供应者不断的讲两种材料放到桌子上,拥有剩下材料的抽烟者卷起 一支烟并抽掉它。如此重复。
int random; //存储随机数
semaphore offer1 = 0; //对应烟草和纸的组合
semaphore offer2 = 0; //对应烟草和胶水组合
semaphore offer3 = 0; //对应纸和胶水的组合
semaphore finish= 0; //表示抽烟已完成
process P1(){
ramdom = 任一随机数;
random = random % 3;
if(random == 0)
V(offer1);
if(random == 1)
V(offer2);
if(random == 2)
V(offer3);
任意两种材料放在桌上;
P(finish);
}
process P2(){ //拥有烟草者
while(1){
P(offer3);
拿纸和胶水,卷成烟,抽掉;
V(finish);
}
}
process P3(){ //拥有纸者
while(1){
P(offer2);
拿烟草和胶水,卷成烟,抽掉;
V(finish);
}
}
process P4(){ //拥有胶水者
while(1){
P(offer1);
拿纸和烟草,卷成烟,抽掉;
V(finish);
}
}
2.4死锁
2.4.1死锁的概念
(1)死锁(deadlock)的定义
所谓死锁,是指多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程都将无法向前推进。
(2)死锁产生的原因
系统资源的竞争; 进程推进顺序非法
(3)死锁产生的必要条件
(1)互斥条件
(2)不剥夺条件
(3)请求并保持条件
(4)循环等待条件
2.4.2死锁的处理策略
破坏产生死锁的4个必要条件之一
死锁预防、避免死锁、死锁的检测和解除
2.4.3死锁预防
(1)破坏互斥条件
(2)破坏不剥夺条件
(3)破坏请求和保持条件(静态分配方法:运行前一次申请完它多需要的全部资源,在它的资源未满足前,不把它投入运行)。
(4)破坏循环等待条件
2.4.4死锁避免
(1)系统安全状态
所谓安全状态,是指系统能按某种进程推进顺序为每个进程pi分配其所需的资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序完成。此时称p1,p2,....pn为安全序列。
(2)银行家算法:采用预分配策略检查分配完成时系统是否处在安全状态。
2.4.5死锁检测和解除
(1)资源分配图(请求边与分配边)
(2)死锁定理
(3)死锁解除:
资源剥夺法:挂起某些死锁进程,并抢占它的资源,以便让其他进程继续推进。
撤销进程法:强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。
进程回退法;让一个或多个进程回退到足以回退死锁的地步。