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