进程的定义
- 进程是程序的一次执行。
- 进程是一个程序及其数据在处理机上执行所发生的的活动。
- 进程是一个程序在数据集上运行的过程,它是系统进行资源分配和调度的独立单位。
进程的三种基本状态
引起进程创建的事件
- 用户登录
- 作业调度
- 提供服务
- 应用请求
进程的创建
- 申请空白PCB
- 为新进程分配空间
- 初始化PCB
- 将新进程插入就绪队列
进程的终止
- 从PCB队列中读出进程
- 终止进程的执行,将处理机分配给其他进程
- 终止其子孙进程
- 回收所有资源
- 从队列删除PCB
进程同步
临界资源
OS 把同一时间只能为一个进程访问的资源成为临界资源。
临界区
进程中访问临界资源的那段代码称为临界区。
同步机制应遵循的规则
- 空闲让进
- 忙则等待
- 让权等待
- 有限等待
信号量机制
整型信号量
最初由Dijkstra 把整型信号量定义成一个整型量,除初始化外仅能通过两个原子操作wait(s)、signal(s)来访问。
wait(s){
while(s<=0){}
s--;
}
signal(s){
s++;
}
记录型信号量
在整型信号量中,S<=0,需要不断测试,处于‘忙等’状态,因为违背了‘让权等待’的准则。在满足让权等待的前提下,多个进程有可能竞争统一临界资源的情况,因此必须有一个资源数目的变量和一个等待链表。为此为原有信号量作以下定义:
type semaphore{
value : Integer,
L :list of process
}
wait(s){
s.value = s.value -1;
if(s.value <0) {
block(s,L);
}
}
signal(s){
s.value = s.value +1;
if(s.value <=0){
wakeup(s,L);
}
}
AND 型信号量
上述进程互斥问题只针对进程之间互斥共享一个资源而言,但有些场景下,一个进程需要获得两个或更多的资源后才能继续执行。所以要保证进程之间同步,就引入了AND型信号量即一次申请进程执行所需的所有资源。
Swait(s1,s2,s3...)
Ssingal(s1,s2,s3...)
信号量的应用
利用信号量实现进程互斥
- 某交通路口设置了一个自动计数系统,该系统由“观察者”进程和“报告者”进程组成。观察者进程能识别卡车,并对通过的卡车计数;报告者进程定时(可设为每隔1小时,准点时)将观察者的计数值打印输出,每次打印后把计数值清“0”。两个进程的并发执行可完成对每小时中卡车流量的统计。这两个进程的功能如下
Semaphore S ;
int count =0;
S.value =1;
process observer(){
while(Condition){
observe a lorry;
wait(S);
count++;
signal(S);
}
}
process reporter(){
wait(S);
print(count);
count =0;
signal(S);
}
利用记录型信号量解决生产者消费者问题
假定在生产者和消费者之间的公用缓冲池中,具有n个缓冲区,这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。对生产者—消费者问题可描述如下:
Semaphore mutex=1;
Semaphore empty=n;
Semaphore full =0;
Queue queue = new Queue(n);
procedurer(e){
wait(empty);
wait(mutex);
queue.offer(e);
signal(mutex);
sugnal(full);
}
consumer(){
wait(full);
wait(mutex);
queue.poll();
signal(mutex);
signal(empty);
}
利用AND型信号量解决生产者消费者问题
Semaphore mutex=1;
Semaphore empty=n;
Semaphore full =0;
Queue queue = new Queue(n);
procedurer(e){
Swait(empty,mutex);
queue.offer(e);
Ssignal(mutex,full);
}
consumer(){
Swait(full,mutex);
queue.poll();
Ssignal(mutex,empty);
哲学家进餐问题
- 至多允许4个哲学家同时取左边的筷子,这样能至少保证一个哲学家能就餐,并在用毕后释放他用过的两只筷子,从而使更多的哲学家能够进餐。(请学生考虑算法的描述)
- 仅当哲学家左右两只筷子均可用时,才允许他拿起筷子进餐。(用AND信号量机制)
- 规定奇数号哲学家先拿左边筷子,然后再拿右边筷子;而偶数号哲学家先拿右边筷子,然后再拿左边筷子。
进程间通信
共享内存
消息传递系统
直接通信
这是指发送进程利用OS所提供的发送命令,直接把消息发送给目标进程。此时,要求发送进程和接收进程都以显式方式提供对方的标识符。通常,系统提供下述两条通信命令(原语):
Send(Receiver, message); 发送一个消息给接收进程;
Receive(Sender, message); 接收Sender发来的消息;
间接通信
信箱通信
管道通信
所谓管道是指连接一个读进程和一个写进程并实现通信的共享文件,又称为pipe文件,以字符流的方式交换信息。主要解决下面三个问题:
- 互斥
- 同步
- 对方是否存在
线程
线程的定义
- 轻型实体
- 独立调度和分派的基本单位
- 可并发执行
- 共享进程资源
线程的分类
- 内核级线程
无论是用户进程中的线程,还是系统进程中的线程,它们的创建、撤消和切换等,都是依靠内核实现的。此外,在内核空间为每一个内核支持线程设置了一个线程控制块, 内核是根据该控制块而感知某线程的存在的,并对其加以控制。 - 用户线程
用户级线程仅存在于用户空间中。这种线程的创建、 撤消、线程之间的同步与通信等功能,都无须利用系统调用来实现。对于用户级线程的切换,通常是发生在一个应用进程的诸多线程之间,无须内核的支持。