标签:info 特权 fetch 队列 临界资源 iter 步骤 描述 指针
进程是程序的一次执行
是一个程序及其数据在处理机上顺序执行时所发生的活动
是具有独立功能的程序在一个数据集合上的一次运行过程
是系统进行资源分配和调度的一个基本单位
是PCB结构、程序和数据的集合
设备分配只针对现有进程,不会创建进程
进程的特征:
进程与程序的区别:
进程执行的间断性,决定了进程可能具有多种状态
运行的进程可能具有就绪、执行、阻塞三种基本状态
当进程已分配到除CPU以外的所有必要资源时,它便处于就绪状态,一旦获得CPU,便立即执行,进入执行状态
正在执行的进程,由于发生某个事件而暂时无法执行时,便放弃处理机而进入阻塞状态
由于执行的进程变为阻塞状态后,调度程序立即把处理机分配给另一个就绪进程(因此,阻塞进程的事件消失后,进程不会立即恢复到执行状态,而转变为就绪状态,重新等待处理机)
为了管理的需要,还存在着两种比较常见的进程状态,即创建状态和终止状态
引起创建的事件:
创建一个进程一般要通过两个步骤:
当一个新进程被创建时,系统已为其分配了PCB,填写了进程标识等信息,但由于该进程所必需的资源或其它信息,如主存资源尚未分配等,一般而言,此时的进程已拥有了自己的PCB,但进程自身还未进入主存,即创建工作尚未完成,进程还不能被调度运行,其所处的状态就是创建状态。
引入创建状态,是为了保证进程的调度必须在创建工作完成后进行,以确保对进程控制块操作的完整性。同时,创建状态的引入,也增加了管理的灵活性,操作系统可以根据系统性能或主存容量的限制,推迟创建状态进程的提交。对于处于创建状态的进程,获得了其所必需的资源,以及对其PCB初始化工作完成后,进程状态便可由创建状态转入就绪状态。
引起终止的事件:
进程的终止也要通过两个步骤:
当一个进程到达了自然结束点,或是出现了无法克服的错误,或是被操作系统所终结,或是被其他有终止权的进程所终结,它将进入终止状态
进入终止态的进程以后不能再执行,但在操作系统中依然保留一个记录,其中保存状态码和一些计时统计数据,供其它进程收集。一旦其它进程完成了对终止状态进程的信息提取之后,操作系统将删除该进程。
阻塞是进程自身的一种主动行为
a. 调用block原语
b. 停止执行,修改PCB进入阻塞队列(一个或多个
唤醒由其他相关进程完成
a. wakeup原语
b. 修改PCB进入就绪队列
为了系统和用户观察分析的需要,还引入了挂起操作,与挂起对应的是激活操作
当进程被挂起,便会进入静止状态:正在执行,便会暂停执行,处于就绪状态则不接受调度
引入挂起状态的原因有:
在引入挂起状态后:
为了描述和控制进程的运行,系统为每个进程定义了一个数据结构——进程控制块PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录型数据结构
PCB 的作用是使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程
在一个系统中,通常可拥有数十个、数百个乃至数千个PCB。为了能对它们加以有效的管理,应该用适当的方式将这些PCB组织起来。目前常用的组织方式有以下两种。
进程控制是进程管理最基本的功能,主要包括创建新进程,终止已完成的进程,将发生异常的进程置于阻塞状态,进程运行中的状态转换等
参数:进程标识、优先级、进程起始地址、CPU初始状态、资源需求等等
创建进程的过程:
进程终止的时机/时间:
终止过程:
阻塞的时机/事件
阻塞过程:进程通过block
原语wakeup,和阻塞成对使用
唤醒过程:先把被阻塞的进程从该事件阻塞队列移出,将其PSB状态改为就绪,再插入就绪队列
临界资源:一次只允许一个进程访问的资源
while(1){
entry; //进入区
critical; //临界区
exit; //退出区
}
各进程应互斥进入相关临界区,所谓临界区是指一段代码,一段程序
同步机制应该遵循:
信号量机制是一种进程间的低级通信方式
s是一个整形量,除了初始化外,仅通过两个原子操作wait(s)和signal(s)访问(也叫P,V操作)
wait(s){
while(s<=0);
s--;
}
signal(s){
s++;
}
互斥关系:A,B共享一个缓冲区,互斥
PA(){
while(1){
wait(s);
// 临界区
signal(s);
// 剩余区
}
}
PB(){
while(1){
wait(s);
// 临界区
signal(s);
// 剩余区
}
}
main(){
s=1; //init
// begin
PA();
PB();
// end
}
前驱关系:P1,P2同步,P2→P1
PA(){
P(s);
a1;
}
PB(){
a2;
V(s);
}
总结:
信号量表示的是临界资源数
初值为2,表示初始时有2个可用的资源,若现在为-1,说明这两个可用资源已经被占用了,而且有一个进程在等待资源
初值为3,表示初始时有3个可用的资源,若现在为1,表示有两个资源被进程访问了,可用资源变为1,没有进程会等待
为了使两个进程同步运行,至少2个信号量
1.桌上有一空盘,允许存放一只水果,爸爸可向盘内放苹果或桔子,儿子专等吃桔子,女儿专等吃苹果
semaphore s,so,sa=1,0,0;
father(){
while(1) {
wait(s);
// 将水果放入盘中;
if(放入的是桔子)
then signal(so);
else signal(sa);
}
}
son(){
while(1){
wait(so);
// 从盘中取出桔子
signal(s);
// 吃桔子
}
}
daughter() {
while(1){
wait(sa);
// 从盘中取出苹果
signal(s);
// 吃苹果
}
}
main()
{
// cobegin
father();
son();
daughter();
// coend
}
2.某寺庙,有小、老和尚若干,由小和尚提水入缸供老和尚饮用,水缸可容10桶水,水取自同一个井中,水井窄,每次只能容一个桶取水,水桶总数3个,每次入缸取水桶仅为1桶,且不可同时进行,试给出有关取水,入水的算法
mutexj = 1;
mutexg = 1;
empty = 10;
full = 0;
count = 3;
old(){
while(1) {
wait(full); //缸中有无水
wait(count); //有无桶
wait(mutexg); //取水前
Fetch from gang;
signal(mutexg);
signal(count);
signal(empty); //通知小
}
}
little(){
while(1) {
wait(empty); //缸中有无空
wait(count); //有无桶
wait(mutexj); //取水前
Fetch from well;
signal(mutexj);
wait(mutexg); //倒水前
pour;
signal(mutexg);
signal(count);
signal(full); //通知老
}
}
整形信号量中S<=0就会不断地测试,未遵循让权等待,而是处于忙等
解决方案:建立一个进程链表list,连结所有等待该类资源的进程
typedef struct{
int value;
struct process_control_block *list
}semaphore;
wait(semaphore *S){
S->value--;
if(S->value < 0)
block(S->list);
}
signal(semaphore *S){
S->value--;
if(S->value <= 0)
wakeup(S->list);
}
要么全分配,要么一个也不分配
不用时有可能发生死锁
Swait(s1,s2,…,sn){
while(1){
if (s1>=1& …&sn >=1){
for(i=1;i<=n;i++) si--;
break;
}
else{
//将进程放入与找到的第一个si<1的si相关的阻塞队列中
//并将该进程的程序计数设置为swait操作的开始
}
}
}
Ssignal(s1,s2,…,sn){
while(1){
for (i=1;i<=n;i++){
si++;
//将与si关联的队列中等待的所有进程都移动到就绪队列中
}
}
}
为提高效率而对AND信号量的扩充
允许一次申请多种资源多个
ti为分配下限值,Si>=ti则不分配,di为该进程需求值
Swait(S1, t1, d1, …, Sn, tn, dn){
while(1){
if(Si>=ti& … &Sn>=tn)
for (i=1;i<=n;i++)
Si=Si-di;
else{
//将进程放在Si<ti的第一个Si的阻塞队列中
//并将该进程的程序计数设置为swait操作的开始
}
}
}
Ssignal(S1, d1, …, Sn, dn){
while(1){
for (i=1;i<=n;i++) {
Si =Si+di;
//将与si关联的队列中等待的所有进程都移动到就绪队列中
}
}
}
Swait(S,d,d):允许每次申请d个资源,少于d不分配
Swait(S,1,1):S>1记录型信号量,S=1互斥形信号量
Swait(S,1,0):可控开关,S>=1时允许同时进入,S<1时不允许
定义数据结构
int n;
typedef item = xxx; //产品类型
item buffer [n]; //缓冲池
int in = 0,out = 0;
int counter = 0; //产品数
缓冲池满时,生产者等待;为空时,消费者等待
记录型信号量
semaphore mutex=1,empty=n,full=0
item buffer[n]; //缓冲池
int in = 0,out = 0;
int main()
{
cobegin:
producer();
consumer();
coend
}
producer(){
while(1){
…
produce an item in nextp;
…
wait(empty);
wait(mutex);
buffer[in]=nextp;
in=(in+1)%n;
signal(mutex);
signal(full);
}
}
consumer(){
while(1) {
wait(full);
wait(mutex);
nextc=buffer[out];
out=(out+1)%n;
signal(mutex);
signal(empty);
consumer the item in nextc;
}
}
P操作的顺序至关重要,顺序不当可能导致死锁(有缓冲池使用权,无缓冲)
V操作的顺序无关紧要
当缓冲区只有一个时,mutex可省略
AND信号量
semaphore mutex=1,empty=n,full=0;
item buffer[n];
int in=0,out=0;
main(){
cobegin
producer();
consumer();
coend
}
producer()
{
while(1)
{
...
produce......;
...
Swait(empty,mutex);
buffer[int]=nextp;
in = (in+1)mod n;
Ssignal(mutex,full);
}
}
consumer(){
while(1){
Swait(full,mutex);
nextc=buffer[out];
out=(out+1)%n;
Ssignal(mutex,empty);
consumer......;
}
}
5个哲学家围坐,用5只筷子吃面,筷子交替摆放
记录型信号量
设5个信号量表示5只筷子
AND信号量
同上
读进程可共享对象,写进程不可
设整形变量readcount读者数,wmutex读写互斥,rmutex互斥访问
记录型信号量:
semaphore rmutex=1,wmutex=1;
int readcount=0;
int main(){
cobegin:
reader();
writer();
coend;
}
reader(){
while(1){
wait(rmutex);
if(readcount==0) wait(wmutex);//无人读才能写
readcount++;
signal(rmutex);
...
read......
...
wait(rmutex);
readcount--;
if(readcount==0) signal(wmutex);
signal(rmutex);
}
}
writer(){
while(1){
wait(wmutex);
...
write......
...
signal(wmutex);
}
}
写优先
semaphore rmutex=1,wmutex=1,s=1;
int readcount=0;
int main(){
cobegin:
reader();
writer();
coend;
}
reader(){
while(1){
wait(s);//!
wait(rmutex);
if(readcount==0) wait(wmutex);//无人读
readcount++;
signal(rmutex);
signal(s);//!
...
read......
...
wait(rmutex);
readcount--;
if(readcount==0) signal(wmutex);
signal(rmutex);
}
}
writer(){
while(1){
wait(s);//!
wait(wmutex);
...
write......
...
signal(wmutex);
signal(s);//!
}
}
信号量集
#define RN 20//最大读者数
semaphore L=RN,mx=1;
int main(){
cobegin:
reader();
writer();
coend;
}
reader(){
while(1){
swait(L,1,1);
swait(mx,1,0);
...
read......
...
wait(rmutex);
ssignal(L,1);
}
}
writer(){
while(1){
swait(mx,1,1);
swait(L,RN,0);
...
write......
...
ssignal(mx,1);
}
}
将同步操作的机制和临界资源结合到一起,避免了要使用临界资源的进程自备同步操作
管程:一个数据结构和能为并发进程所执行的一组操作
包括:1. 局部对于管程的共享变量,2. 对该数据结构操作的一组过程,3. 对局部管程数据设初值
Monitor m_name{ //管程名
variable declarations; //共享变量说明
cond declarations; //条件变量说明
public: //能被进程调用的过程
void P1(…); //对数据结构的操作过程
{}
void P2(…);
{}
...
void Pn(…);
{}
...
{
//管程主体
//初始化代码
}
}
建立管程PC,包括:
Monitor PC{
item buffer[N];
int in out;
condition notfull,notempty;
int count;
public:
void put(item x){
if(count>=N)cwait(notfull);
buffer[in]=x;
in=(in+1)%N;
count++;
csignal(notempty);
}
void get(item x){
if(count<=0)cwait(notempty);
x=buffer[out];
out=(out+1)%N;
count--;
csignal(notfull);
}
}
void producer(){
item x;
while(1){
//produce
PC.put(x);
}
}
void consumer(){
item x;
while(1){
PC.get(x);
//consume
}
}
标签:info 特权 fetch 队列 临界资源 iter 步骤 描述 指针
原文地址:https://www.cnblogs.com/zhxmdefj/p/12059174.html