进程管理实验-C语言版
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void send(int sender,int receiver,int snum) 发送 q=pcb[receiver].mess; q指向接收者消息等 待队列首 if(q==NULL) pcb[receiver].mess=p; q空则p插入队首 else { while(q->next!=NULL) q=q->next; q移到队尾 q->next=p; } 将p链接到队尾 }
数据结构
(1)每个进程有一个进程控制块PCB,内容包括: id 进程标识号,id=0,1,2; status 进程状态,可为e,r,t,w,c; priority 进程优先数; nextwr 等待链指针,指示在同一信号量上等待的 下一个进程的标识号。 (2)信号量semaphore,对应于临界资源S1和S2分别 有sem1和sem2,均为互斥信号量,内容包括: value 信号量,初值为1; firstwr 等待链首指针,指示在同一信号量上等待 的下一个进程的标识数。
{
proce block(); 阻塞 proce wakeup(); 唤醒
int w; 工作指针 printf("process %d is blocked\n",exe); pcb[exe].status='w'; 置阻塞态 pcb[exe].nextwr=NIL; w=sem[se].firstwr; 信号量等待队列头指针赋给w if (w==NIL) sem[se].firstwr=exe; 空则当前进程作队头 else { while (pcb[w].nextwr!=NIL) w=pcb[w].nextwr; 指针后退到队尾 pcb[w].nextwr=exe; } 当前进程链接到队尾
if (pcb[j].priority<w){ w=pcb[j].priority; pd=j; }
if (pd==NIL) for(j=1;j<=3;j++) 再在低就绪态中找优先数最小的进程 if (pcb[j].status=='t')
if(pcb[j].priority<w){ w=pcb[j].priority; pd=j; }
基本思路
进程调度算法采用剥夺式最高优先数法。各进程的 优先数通过键盘输入予以静态设置。调度程序每次总是 选择优先数最小(优先权最高)的就绪进程投入执行。 先从r状态进程中选择,再从t状态进程中选择。当现行 进程唤醒某个等待进程,且被唤醒进程的优先数小于现 行进程时,则剥夺现行进程的执行权。 各进程在使用临界资源S1和S2时,通过调用信号量 sem1和sem2上的P、V操作来实现同步。阻塞和唤醒操 作负责完成从进程的执行态到等待态以及从等待态到就 绪态的转换。 系统启动后,在完成必要的系统初始化后便执行进 程调度程序。当执行进程因“时间片中断”,或被排斥 使用临界资源,或唤醒某个进程时,立即进行进程调度。 当3个进程都处于完成状态后,系统退出运行。
调度
int timeint(char ad)
模拟时间片中断
{ float x; x为0~1之间的随机数 x=random(); if((x<0.33)&&(exe==0)) return false; 若在各自的时间片不产 生中断 else if((x<0.66)&&(exe==1)) return false; else if((x<1.00)&&(exe==2)) return false; else { 否则产生时间片中断 pcb[exe].inum=i; 保护现场 pcb[exe].addr=ad; pcb[exe].status='t'; 置为低就绪态 printf("time slice interrupt.\n"); printf("process %d enter into ready\n",exe); exe=NIL; 执行进程置空 return true; 中断标志置真 } }
#define MAXPRI 100 #define NIL -1 struct procb{ PCB类型 int id; 进程号 char status; 进程状态 int nextwr; 等待号 message mess; 消息队指针 int inum; 运行次数, char addr; 返回地址 int priority; 优先数 };
}
void wakeup(int se)
{ int w; w=sem[se].firstwr; 队列头指针赋给w if (w!=NIL){非空则摘下首块 sem[se].firstwr=pcb[w].nextwr;重链接 pcb[w].status='r';置为高就绪态 printf("process %d is wakeup\n",w);
读入优先数 运行次数, 地址
} sem[1].value=1; sem[1].firstwr=NIL; 对信号量初始化 sem[2].value=1; sem[2].firstwr=NIL; exe=NIL; 当前执行进程号置为空
}
func proc eexit(n:integer); float random:real; random( ) 产生 0~1之间的随机数 {int m; seed为int 型,实际值在-32768到32767之间 if seed<0 m=-seed; else m=seed; seed=(25171*seed+13841)%65536; return(m/32767.0); } void eexit(int n); 退出
支持多个进程并发运行的简单进程 管理模拟系统
题目
本系统的同步机构采用信号量上的P、V操作的机制; 控制机构包括: (1)阻塞和唤醒操作; (2)时间片中断处理程序模拟时间片中断; (3)进程调度程序负责为各进程分配处理机。 系统中涉及了3个并发进程。它们之间的关系是: (1) 3个进程需要互斥使用临界资源S2。 (2)进程1和进程2又需互斥使用临界资源S1. 本系统在运行过程中随机打印出各进程的状态变换过 程,系统的调度过程及公共变量的变化情况。
}
func p( );, func v(ad) ); wait操作 int p(intse char { sem[se].value=sem[se].value-1; 信号量减1 if sem[se].value>=0 return false; 有资源不等待 else { block(se); 阻塞到 se 等待队列 pcb[exe].inum=i; pcb[exe].addr=ad; 保护现场 exe=NIL; return true; 执行进程置空,等待标志
数据结构
(3)现场保留区,用数组savearea[3][4]表示。即每 个进程都有一个大小为4个单元的保留区,用来保存被 “中断”时的现场信息,如通用寄存器的内容和断点地 址等。 此外,系统中还用到下列主要全程变量: exe 执行进程指针,其值为进程标识号; i 用来模拟一个通用寄存器; addr 用来模拟程序计数器; s1,s2 两个公共变量,用作共享临界资源
void send(int sender,int receiver,int snum) 发送
{ struct message p,q; 工作指针 p=(message)malloc(sizeof(struct messagetp)); p->num=snum; 申请消息块,写入缓冲 p->next=NULL;下一指针置空 p->pro=sender;置发ห้องสมุดไป่ตู้者 printf(“send message to process %d” ,receiver); printf(“process %d already run %d times”,sender,snum);
void receive(int receiver)
接收
{ message p,q; 工作指针 p=pcb[receiver].mess; p指向接收者消息等待队列首 while(p!=NULL) { 显示发送者和接收者信息 printf(“receive message from process %d”,p->pro); printf(“process %d is already run %d times”,p>pro, p->num); q=p; 陆续将接收过的的消息块删除并释放 p=p->next; free(q); } pcb[receiver].mess=NULL; 接收完后消息等待队列置
struct messagetp{ int num; message next; int pro; };
消息块类型(信息,指针,发送者号)
typedef struct messagetp *message; 指向消息块指针类型 struct semaphorel{ 信号量类型(信号量,等待队头号) int value; int firstwr; }; struct procb pcb[3]; PCB表 struct semaphorel sem[2]; 信号量表 char addr; 当前进程地址 int i,seed,exe; 运行次数,随机变量,当前运行进程号
基本思路
系统为进程设置了5种运行状态: e—执行态;r—高就绪态;t—低就绪态(执行进程因 时间片到限而转入);w—等待态;c—完成态。各进程 的初始状态均设置为r. 系统分时执行各进程,并规定3个进程的执行概率均 为33%。通过产生随机数x来模拟时间片。当进程 process1访问随机数x时,若x>=0.33;当进程process2访 问x时,若x<0.33或x>=0.66;当进程process3访问x时,若 x<0.66,则分别认为各进程的执行时间片到限,产生 “时间片中断”而转入低就绪态t。
空
}
void init()
初始化
{ int j; for(j=1;j<=3;j++) 初始化各进程控制块 { pcb[j].id=j; pcb[j].status='r'; 进程号,进程状态 pcb[j].nextwr=NIL; pcb[j].mess:=NULL; 等待、消息
指针
printf(“process %d priority?”, j); scanf(“%d”,&pcb[j].priority); pcb[j].inum=0; pcb[j].addr='0';
{
pcb[n].status='c'; 本进程置为完成态 printf("process %d is completed\n",n); exe=NIL; 当前执行进程号置空
}
int find()
选进程
{ int j,pd,w; pd=NIL; w=MAXPRI; for(j=1;j<=3;j++) 先在高就绪态中找优先数最小的进程 if (pcb[j].status=='r')
置真
} } int v(int se,char ad) signal操作 { sem[se].value=sem[se].value+1; 信号量加1 if sem[se].value>0 return false; 无等待不重新调度 else { wakeup(se); 有等待唤醒 se 等待队列的进程 pcb[exe].inum=i; pcb[exe].addr=ad; 保护现场 return true; 要重新
return pd; 返回进程号
int scheduler() 调度
{ int pd; pd=find(); 找优先进程 if ((pd==NIL)&&(exe==NIL)) return NIL; else{ if (pd!=NIL){ 若有就绪进程则 if(exe==NIL) { 若当前没有进程执行则 pcb[pd].status=‘e’; 新进程置执行态 exe=pd; printf(“process %d is executing\n”,exe); } else if (pcb[pd].priority<pcb[exe].priority){ 切换 pcb[exe].status=‘r’; 原执行进程置高就绪态 printf("process %d enter into ready\n",exe); pcb[pd].status=‘e’; 新进程置执行态 exe=pd; printf("proecess %d is executing\n",exe);} } i=pcb[exe].inum; 恢复现场