进程管理实验报告.docx
- 文档编号:24272375
- 上传时间:2023-05-25
- 格式:DOCX
- 页数:17
- 大小:18.46KB
进程管理实验报告.docx
《进程管理实验报告.docx》由会员分享,可在线阅读,更多相关《进程管理实验报告.docx(17页珍藏版)》请在冰豆网上搜索。
进程管理实验报告
实验名称:
进程管理
实验要求:
阅读后面的C语言实例,修改程序,使其优先数在运行期间可以变化(动态优先数)。
例如,当某进程被时间片中断次数增加到一定数目时,提高其优先权。
关键问题:
读懂源程序代码,了解进程管理的方式,并设计一个算法使程序能在运行过程中修改进程优先级。
设计思路:
在进程控制块中定义一个记录进程中断次数的变量,在block函数中设置跟踪并记录进程中断次数,在调度函数schedule中设置算法,在进程中断3次后将该进程的优先级提升至最高。
改动后的代码:
#include
#defineTRUE1
#defineFALSE0
#defineMAXPRI100
#defineNIL-1
//进程控制块
struct{
intid;//进程号
charstatus;//进程状态,'e'-执行态'r'-高就绪态't'-低就绪态'w'-等待态'c'-完成态
intnextwr;//等待链指针,指示在同一信号量上等待的下一个等待进程的进程号。
intpriority;//进程优先数,值越小,优先级越高。
intc;//进程中断次数
}pcb[3];//共3个进程
//s1、s2为三个进程共享的变量;seed为随机值;registeri模拟寄存器值,存放计算的重复次数。
intregisteri,s1,s2,seed,exe=NIL;//exe为当前运行(占有cpu)的进程号
//2个信号量sem[0]、sem[1],分别与共享变量s1、s2相联系。
//对应信号量sem[0]、sem[1]分别有两个阻塞队列,队列首由sem[].firstwr指定,队列链指针是pcb[].nextwr
struct{
intvalue;//信号量值
intfirstwr;//等待该信号量的阻塞队列的首个进程号
}sem[2];
//三个进程的现场保留区,其中savearea[][0]为寄存器内容,savearea[][1]为下一条指令地址。
charsavearea[3][4];
charaddr;//当前执行程序的当前指针
voidmain();
voidinit();
floatrandom();
inttimeint(charad);
intscheduler();
intfind();
intp(intse,charad);
voidblock(intse);
intv(intse,charad);
voidwakeup(intse);
voidprocess1();
voidprocess2();
voidprocess3();
voideexit(intn);
//--------------------------------------------------------------------
//主程序
voidmain()
{
intcurrentProcess;
printf("进程管理器\n");
init();
printf("s1=%d,s2=%d\n",s1,s2);
printf("进程1、进程2、进程3已经准备好!
\n");
for(;;)
{
currentProcess=scheduler();//进程调度,选择优先级别最高的就绪进程运行。
if(currentProcess==NIL)
break;//所有进程已经运行完毕,结束。
switch(currentProcess)//运行当前进程代码
{
case0:
process1();
break;
case1:
process2();
break;
case2:
process3();
break;
default:
printf("进程号出错!
\n");
break;
}
}
printf("最后结果:
s1=%d,s2=%d\n",s1,s2);
}
//------------------------------------------------------------------------
//初始化
voidinit()
{
inti,j;
s1=0;s2=0;
//生成进程控制块
for(j=0;j<3;j++)
{
pcb[j].id=j;//进程号
pcb[j].status='r';//进程初始状态为高就绪状态
pcb[j].nextwr=NIL;
printf("\n进程%d的优先数?
",j+1);
scanf("%d",&i);
pcb[j].priority=i;//进程优先级
pcb[j].c=0;
}
//初始化两个信号量
sem[0].value=1;//与s1相联系
sem[0].firstwr=NIL;
sem[1].value=1;//与s2相联系
sem[1].firstwr=NIL;
//初始化现场保留区。
每个进程均有现场保留区。
for(i=1;i<3;i++)
for(j=0;j<4;j++)
savearea[i][j]='0';
}//endofinit()
//----------------------------------------------------------------------------------
//生成0~1之间随机值
floatrandom()
{
intm;
if(seed<0)m=-seed;
elsem=seed;
seed=(25173*seed+13849)%65536;
return(m/32767.0);
}
//----------------------------------------------------------------------------------
//检测当前进程的时间片是否已到。
未到,返回FALSE,否则返回TRUE。
系统采用分时执行,
//规定每个进程的执行概率为33%,用产生数x模拟时间片。
//ad为程序的当前语句地址。
inttimeint(charad)
{
floatx;
x=random();
if((x<0.33)&&(exe==0))return(FALSE);//当前进程为进程1,时间片未到。
if((x>=0.33)&&(x<0.66)&&(exe==1))return(FALSE);//当前进程为进程2,时间片未到。
if((x>=0.66)&&(x<1)&&(exe==2))return(FALSE);//当前进程为进程3,时间片未到。
//时间片已到处理:
置正在执行进程状态为低就绪,处理器空闲。
savearea[exe][0]=registeri;//保存通用寄存器内容
savearea[exe][1]=ad;//保存程序指针
pcb[exe].status='t';//状态改为低就绪态
printf("时间片中断,进程%d转入就绪态\n",exe+1);
exe=NIL;
return(TRUE);
}
//-----------------------------------------------------------------------------------
//进程调度:
选择一个进程投入运行。
返回当前进程的进程号。
intscheduler()
{
intpd;
//选择投入运行的进程pd
if((pd=find())==NIL&&exe==NIL)
return(NIL);//无进程可运行,将结束。
if(pd!
=NIL)
{
if(exe==NIL)//选中了进程且处理器空闲,则投入运行。
{
pcb[pd].status='e';
exe=pd;
printf("进程%d正在执行\n",exe+1);
}
elseif(pcb[pd].priority { //将当前进程转入高就绪状态 pcb[exe].status='r'; printf("进程%d进入就绪状态\n",exe+1); //选中进程pd投入执行 pcb[pd].status='e'; exe=pd; printf("进程%d正在执行\n",exe+1); } } //恢复进程现场 registeri=savearea[exe][0];//恢复当前进程的寄存器。 addr=savearea[exe][1];//恢复执行进程的程序指针 //修改优先权 if(pcb[pd].c==3){ pcb[pd].c=0; pcb[pd].priority=0; printf("\n! ! 进程%d中断次数达到3,优先级提高\n",pd+1); } return(exe);//返回当前进程的进程号 } //--------------------------------------------------------------------------------- //在3个进程中按就绪状态及其优先数选出进程。 返回选出的进程号。 intfind() { intj,pd=NIL,w=MAXPRI; for(j=0;j<3;j++)//选择高就绪状态优先级最高的进程 { if((pcb[j].status=='r')&&(pcb[j].priority { w=pcb[j].priority; pd=j; } } if(pd==NIL)//没有高就绪状态的进程,寻找低就绪状态的进程。 { for(j=0;j<3;j++) { if((pcb[j].status=='t')&&(pcb[j].priority { w=pcb[j].priority; pd=j; } } } return(pd); } //-------------------------------------------------------------------------------------- //P操作,申请资源。 若申请se号资源成功,返回FALSE,若失败,把当前进程挂入se号资源的阻塞队列, //让出cpu,返回TRUE. //se为资源号,ad为程序当前指令的地址。 intp(intse,charad) { if(--sem[se].value>=0) return(FALSE);//资源申请成功 //资源申请失败处理: block(se);//把当前进程挂入se号资源的阻塞队列 savearea[exe][0]=registeri;//保存当前进程的寄存器内容 savearea[exe][1]=ad;//保存当前进程的下一条指令地址 exe=NIL;//让出CPU return(TRUE);//资源申请失败 } //---------------------------------------------------------------------------- //把当前进程阻塞,并挂到资源se的阻塞队列。 voidblock(intse) { intw; inti; i=(se==0)? 1: 2; printf("进程%d申请s%i时被阻塞\n",exe+1,i); pcb[exe].status='w';//当前进程被阻塞 pcb[exe].c++; printf("进程%d中断次数+1,当前为%d\n",exe+1,pcb[exe].c); pcb[exe].nextwr=NIL; if((w=sem[se].firstwr)==NIL)//se资源的阻塞队列空,w为队列的首个进程号。 sem[se].firstwr=exe;//当前进程为阻塞队列第一个进程 else { while(pcb[w].nextwr! =NIL)//寻找队列的最后一个进程w w=pcb[w].nextwr; pcb[w].nextwr=exe;//将阻塞进程挂到队列尾部 } } //--------------------------------------------------------------------------------------------- //V操作,释放资源se。 若无进程等待se资源,返回FALSE;若有进程等待se资源,将该等待进程置为高就绪状态, //保存当前进程现场,返回TRUE(将引起重新调度). //se为资源号,ad为当前指令的地址。 intv(intse,charad) { if(++sem[se].value>0) return(FALSE);//释放资源后,无等待该资源的进程,返回。 //有进程在等待该资源,则唤醒它。 wakeup(se);//唤醒等待资源se的进程。 //保存当前进程(执行态)的现场,因为后面将引起处理器重新调度。 savearea[exe][0]=registeri;//保存寄存器 savearea[exe][1]=ad;//保存指令指针 return(TRUE); } //--------------------------------------------------------------------------------------------- //将等待se资源的首个进程置为高就绪状态(唤醒) voidwakeup(intse) { intw; inti; i=(se==0)? 1: 2; w=sem[se].firstwr;//取资源se阻塞队列的首个进程w if(w! =NIL) { sem[se].firstwr=pcb[w].nextwr;//调整阻塞队列首指针 pcb[w].status='r';//将w进程置为高就绪态 printf("进程%d被唤醒,得到资源s%d\n",w+1,i); } } //------------------------------------------------------------------------------------------- //进程1的程序代码,完成5次的重复计算: s1=s1+1;s2=s2+1; //该程序退出后将进行重新调度。 voidprocess1() {//根据当前当前指令地址跳转 if(addr=='a')gotoa1; if(addr=='b')gotob1; if(addr=='c')gotoc1; if(addr=='d')gotod1; if(addr=='e')gotoe1; if(addr=='f')gotof1; //该程序的首次执行 for(registeri=1;registeri<6;registeri++) { //程序执行s1=s1+1计算: if(p(0,'a'))//申请s1对应信号量sem[0]。 若申请失败,则当前进程被阻塞,'a'为中断地址,即下次恢复执行时地址。 break;//退出。 当前进程被阻塞。 //可以使用s1,但要检查时间片是否到限。 a1: printf("进程1得到s1,正在临界区1\n"); if(timeint('b'))//检查该进程的时间片是否到。 若到,阻塞进程,'b'为中断地址。 break;//退出,重新调度。 //完成计算 b1: printf("s1=%d\n",++s1);//s1=s1+1 if(v(0,'c'))//释放信号量sem[0]。 如有等待该信号量的进程,则退出。 ’c’为中断地址。 break;//退出。 重新调度。 //程序执行s2=s2+1计算: c1: if(p(1,'d'))//申请s2对应信号量。 如申请失败,则当前进程被阻塞。 break;//退出。 当前进程阻塞。 //可以使用s2. d1: printf("进程1得到s2,正在临界区2\n"); if(timeint('e'))//检查进程1的时间片是否到限。 break;//时间片到限,退出。 重新调度。 //使用s2 e1: printf("s2=%d\n",++s2);//s2=s2+1 if(v(1,'f'))//释放信号量 break;//有进程等待该信号量,退出。 重新调度。 f1: printf("进程1循环计算次数=%d\n",registeri); }//for循环 if(registeri<6)return;//计算任务未完成 eexit(0);//任务完成。 结束进程1。 } //---------------------------------------------------------------------------------------- //进程2的程序代码,完成5次的重复计算: s2=s2+1;s1=s1+1; voidprocess2() { if(addr=='a')gotoa2; if(addr=='b')gotob2; if(addr=='c')gotoc2; if(addr=='d')gotod2; if(addr=='e')gotoe2; if(addr=='f')gotof2; //从这里开始执行 for(registeri=1;registeri<6;registeri++) { //进程执行s2=s2+1计算: if(p(1,'a'))//申请s2对应信号量。 若失败,当前进程被阻塞。 break;//退出。 重新调度。 //可以使用s2 a2: printf("进程2得到s2,正在临界区2\n"); if(timeint('b'))//检查进程的时间片是否到限 break;//时间片到,退出。 重新调度。 b2: printf("s2=%d\n",++s2);//计算s2=s2+1 if(v(1,'c'))//释放信号量。 break;//有进程正在等待该信号量,退出,重新调度。 //进程执行s1=s1+1计算: c2: if(p(0,'d'))//申请s1对应信号量。 若失败,进程被阻塞。 break;//进程阻塞,退出,重新调度。 //可以使用s1 d2: printf("进程2得到s1,正在临界区1\n"); if(timeint('e'))//检查进程的时间片是否到。 若到,阻塞进程。 break;//时间片到,退出,重新调度。 e2: printf("s1=%d\n",++s1);//计算s1=s1+1 if(v(0,'f'))//释放信号量。 break;//有进程正在等待该信号量,退出,重新调度。 f2: printf("进程2循环计算次数=%d\n",registeri); }//for循环6次 if(registeri<6)return;//计算未结束 eexit (1);//计算结束。 停止进程2。 } //----------------------------------------------------------------------------------------- //进程3的程序代码,完成5次的重复计算: s2=s2+1; voidprocess3() { if(addr=='a')gotoa3; if(addr=='b')gotob3; if(addr=='c')gotoc3; for(registeri=1;registeri<6;registeri++) { //进程执行s2=s2+1计算: if(p(1,'a'))//申请s2对应信号量。 break;//退出 //可以使用s2 a3: printf("进程3得到s2,正在临界区2\n"); if(timeint('b'))//检查进程的时间片是否到 break;//退出 b3: printf("s2=%d\n",++s2);//计算s2=s2+1 if(v(1,'c'))//释放信号量 break; c3: printf("进程3循环计算次数=%d\n",registeri); }//for循环 if(registeri<6)return; eexit (2);//结束进程3 } //------------------------------------------------------------------------------------------- //进程结束。 n为进程号。 voideexit(intn) { pcb[n].status='c';//置进程状态为完成态 printf("进程%d已经完成\n",n+1); exe=NIL;//让出处理器 }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 进程 管理 实验 报告