操作系统课程设计实验报告.docx
- 文档编号:27845576
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:107
- 大小:1.11MB
操作系统课程设计实验报告.docx
《操作系统课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告.docx(107页珍藏版)》请在冰豆网上搜索。
操作系统课程设计实验报告
操作系统课程设计报告
时间:
2013-12-30~2014-1-10
地点:
信息技术实验中心
计算机科学与技术专业
2011级2班15号
@@@@
2014-1-10
一、课程设计的目的和意义
本次操作系统课程设计的主要任务是进行系统级的程序设计。
本课程设计是操作系统原理课程的延伸。
通过该课程设计,使学生更好地掌握操作系统各部分结构、实现机理和各种典型算法,加深对操作系统的设计和实现思路的理解,培养学生的系统设计和动手能力,学会分析和编写程序。
课程设计的实施将使学生在以下几个方面有所收获:
(1)加深对操作系统原理的理解,提高综合运用所学知识的能力;
(2)培养学生自主查阅参考资料的习惯,增强独立思考和解决问题的能力;
(3)通过课程设计,培养严谨的科学态度和协作精神。
二、进程调度算法模拟
1、设计目的
(1)通过动态优先权算法的模拟加深对进程概念和调度过程的理解。
(2)理解进程控制块的结构。
(3)理解进程运行的并发性。
(4)掌握进程调度算法。
2、设计要求
(1)用C语言实现对N个进程采用动态优先权调度的调度。
(2)每个用来标识进程的进程控制块PCB可用结构来描述,包括以下字段:
•进程标识数ID。
•进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高。
•进程已占用CPU时间CPUTIME。
•进程还需占用的CPU时间ALLTIME。
当进程运行完毕时,ALLTIME变为0。
•进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,进程将进入阻塞状态。
•进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。
• 进程状态STATE。
• 队列指针NEXT,用来将PCB排成队列。
(3)优先数改变的原则:
•进程在就绪队列中呆一个时间片,优先数增加1。
•进程每运行一个时间片,优先数减3。
(4)假设在调度前,系统中有5个进程,它们的初始状态如下:
ID01234
PRIORITY93830290
CPUTIME00000
ALLTIME33634
STARTBLOCK2-1-1-1-1
BLOCKTIME30000
STATEREADYREADYREADYREADYREADY
(5)为了清楚地观察每个进程的调度过程,程序应将每个时间片内的进程的情况显示出来,包括正在运行的进程,处于就绪队列中的进程和处于阻塞队列中的进程。
具体的参照格式如下:
RUBNINGPROG:
i
READY_QUEUE:
->id1->id2
BLOCK_QUEUE:
->id3->id4
ID01234
PRIORIYP0P1P2P3P4
CPUTIMEC0C1C2C3C4
ALLTIMEA0A1A2A3A4
STARTBLOCKT0T1T2T3T4
BLOCKTIMEB0B1B2B3B4
STATES0S1S2S3S4
3、使用动态优先权的进程调度算法的模拟
3.1算法思路分析
通过C程序模拟动态优先权程序调度算法,主要思路和方法就是,通过结构体模拟计算机的控制模组,构造一个进程控制块结构体,用来记录当前进程的的相关状态信息,包括进程标识符、处理机状态、进程调度信息、进程控制信息。
并通过C语言模拟计算机的相关调度算法,对构建的PCB进程进行模拟调度和运行,从而实现用计算机对进程的调度过程进行过程仿真。
当系统空闲(就绪队列为空)时,系统运行闲逛进程,否则运行其他进程,发生变迁(就绪→运行)。
在运行进程(包括闲逛进程)的过程中,可能发生变迁(运行→阻塞),即将运行进程插入到阻塞队列(闲逛进程不能被阻塞),可能有其他新的进程创建进程控制块,还可能唤醒阻塞队列中的某些进程进程控制块,发生变迁(阻塞→就绪),即从阻塞队列中移出并插入就绪队列中。
时间片运行结束后,若进程累计占用CPU时间大于等于进程需要运行的时间,则进程执行结束,释放其PCB。
若进程累计占用CPU时间小于进程需要运行时间,发生变迁4(运行→就绪),即将当前运行的进程插入就绪队列中。
3.2主要数据结构设计
enumSTATE{Ready,Run,Block,RunOut};列举出进程的状态
structPROCESS{
intID;进程的标示符
intPriority;进程优先级
intCputime;进程已占用CPU时间
intAlltime;进程还需占用CPU时间
intStartblock;进程进入阻塞时间
intBlocktime;阻塞时间
enumSTATEState;进程状态
}
3.3算法流程图
执行的进程优先级减3,所需时间片减1,等待的进程优先级加1
N
Y
N
Y
N
Y
图2-1
3.4算法代码实现
#include
#defineN5
voidinit();
voidprint();
intgetRunning();
voidsort();
intrun(inttime);
enumSTATE{Ready,Run,Block,RunOut};
structPROCESS{
intID;
intPriority;
intCputime;
intAlltime;
intStartblock;
intBlocktime;
enumSTATEState;
}Process[N];
intREADY[N];
intBLOCK[N];
intRUNOUT[N][2];
intmain()
{
intTime=0;
init();
printf("Time:
%d\n",Time);
sort();
print();
while
(1)
{
Time++;
getchar();
printf("Time:
%d\n",Time);
if(run(Time))break;
//sort();
}
//print(Time);
return0;
}
voidinit()
{
inti;
//printf("Inputpropertiesof%dprocess(PRIORITY,ALLTIME,STARTBLOCK,BLOCKTIME):
\n",N);
for(i=0;i { READY[i]=-1; BLOCK[i]=-1; RUNOUT[i][0]=-1; RUNOUT[i][1]=-1; Process[i].ID=i; Process[i].Cputime=0; Process[i].State=Ready; //printf("Number%d: ",i); //scanf("%d,%d,%d,%d",&Process[i].Priority,&Process[i].Alltime,&Process[i].Startblock,&Process[i].Blocktime); Process[i].Startblock=-1; Process[i].Blocktime=0; } Process[0].Priority=8; Process[0].Alltime=3; Process[0].Startblock=2; Process[0].Blocktime=3; Process[1].Priority=15; Process[1].Alltime=13; Process[2].Priority=30; Process[2].Alltime=6; Process[3].Priority=24; Process[3].Alltime=8; Process[4].Priority=3; Process[4].Alltime=4; } voidprint() { inti; if(getRunning()>=0)printf("\tRUNNINGPROG: %d\n",getRunning()); printf("\tREADY_QUEUE: "); for(i=0;i { if(READY[i]>=0)printf("->%d",Process[READY[i]].ID); elsebreak; } printf("\n\tBLOCK_QUEUE: "); for(i=0;i { if(BLOCK[i]>=0)printf("->%d",Process[BLOCK[i]].ID); elsebreak; } printf("\n---------------------------------------------------------\n"); printf("ID\t"); for(i=0;i { printf("\t%d",Process[i].ID); } printf("\nPRIORITY"); for(i=0;i { printf("\t%d",Process[i].Priority); } printf("\nCPUTIME"); for(i=0;i { printf("\t%d",Process[i].Cputime); } printf("\nALLTIME"); for(i=0;i { printf("\t%d",Process[i].Alltime); } printf("\nSTARTBLOCK"); for(i=0;i { printf("\t%d",Process[i].Startblock); } printf("\nBLOCKTIME"); for(i=0;i { printf("\t%d",Process[i].Blocktime); } printf("\nSTATE\t"); for(i=0;i { switch(Process[i].State) { case0: printf("\tReady");break; case1: printf("\tRun"); if(Process[i].Alltime==0) { Process[i].State=RunOut; } elseProcess[i].State=Ready; break; case2: printf("\tBlock");break; case3: printf("\tRunOut");break; } } printf("\n"); printf("\tRUNOUTLIST: "); for(i=0;i { if(RUNOUT[i][0]>=0)printf("->%d(%d)",Process[RUNOUT[i][0]].ID,RUNOUT[i][1]); else{printf("\n");break;} } printf("\n"); } intgetRunning() { inti; for(i=0;i { if(Process[i].State==Run) returni; } for(i=0;i { if(Process[i].Startblock==0) returni; } return-1; } voidsort() { inti,j,k; for(i=0;i { READY[i]=-1; BLOCK[i]=-1; } for(i=0;i { if(Process[i].State==Ready||Process[i].State==Run) { //Process[i].State=Ready; if(Process[i].Alltime==0)continue; for(j=0;j { if(READY[j]<0) { READY[j]=i; break; } elseif(Process[i].Priority<=Process[READY[j]].Priority) {continue;} else { for(k=N-1;k>j;--k){READY[k]=READY[k-1];} READY[j]=i; break; } } } elseif(Process[i].State==Block) { for(j=0;j { if(BLOCK[j]<0) { BLOCK[j]=i; break; } elseif(Process[i].Blocktime>=Process[BLOCK[j]].Blocktime) {continue;} else { for(k=N-1;k>j;--k){BLOCK[k]=BLOCK[k-1];} BLOCK[j]=i; break; } } } } } intrun(inttime) { inti,runnum; runnum=READY[0]; if(runnum<0&&BLOCK[0]<0) { printf("EveryprocessisOVER! \n"); return1; } else { if(runnum>=0) { Process[runnum].Priority-=3; Process[runnum].Alltime-=1; Process[runnum].Cputime+=1; Process[runnum].State=Run; for(i=0;i { if(i! =runnum) { if(Process[i].State==Ready){Process[i].Priority+=1;} elseif(Process[i].State==Block) { Process[i].Blocktime-=1; if(Process[i].Blocktime==0){Process[i].State=Ready;} } } } //print(); if(Process[runnum].Alltime==0) { //Process[runnum].State=RunOut; for(i=0;i { if(RUNOUT[i][0]<0) { RUNOUT[i][0]=runnum; RUNOUT[i][1]=time; break; } } } elseif(Process[runnum].Startblock>=0) { Process[runnum].Startblock-=1; if(Process[runnum].Startblock==0) { Process[runnum].State=Block; //Process[runnum].Startblock-=1; } } } elseif(BLOCK[0]>=0) { for(i=0;i { if(Process[i].State==Block) { Process[i].Startblock=-1; Process[i].Blocktime-=1; if(Process[i].Blocktime==0) { Process[i].State=Ready; } } } //print(); } } sort(); print(); return0; } 3.5算法运行分析 图2-2 Time=0时初始化5个进程的各种属性 图2-3 Time=1时运行第一个进程,由于初始的的时候进程2的优先级为30,是最高的,所以第一个时间片的时候先运行的是进程2,运行结束以后进程的2的优先级减3,其他的进程优先级加1,并且进程2的cputime加1,alltime减1,READY_QUEUE按照优先级降序排列。 STATE表示进程的当前状态。 图2-4 Time=2时继续按照上述的规则进行运行 图2-5 Time=3时进程3优先级变成最高的,所以优先的运行进程3。 运行结束后进程的优先级减3,其他进程的优先级加1,进程3的cputime加1,alltime减1。 READY_QUEUE按照优先级降序排列。 图2-6 当time=12时进程2运行的次数等于它的alltime,运行结束,加入RUNOUT中,下一个时间片它的STATE将变成RUNOUT。 图2-7 Time=16时,进程0的由于在前面运行过两次,所以进程0的STARTTIME每次减1,两次后变成0,所以进程0的状态由就绪转变为阻塞,放到阻塞队列中。 此后每过一个时间片,进程0的BLOCKTIME减1。 图2-8 Time=34时每个进程的alltime都等于0,所有的进程都运行结束。 三、动态分区算法的模拟 1、设计目的 了解动态分区方式中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现方式的理解。 2、设计要求 用C语言分别实现采用首次适应算法和最适应算法的动态分区分配过程alloc()和回收过程free()。 其中,空闲分区通过空闲分区链来管理;在进行内存分区时,系统优先使用空闲分区低端的空间。 假设初始态下,可用内存空间为640K,并有下列请求序列,请分别用首次适应算法和最佳适应算法为作业分配和回收内存块,并显示出每次分配和回收后的空闲分区链的情况来以及内存占用情况图。 作业1申请130K 作业2申请60K 作业3申请100k 作业2释放60K 作业4申请200K 作业3释放100K 作业1释放130K 作业5申请140K 作业6申请60K 作业7申请50K 作业6释放60K 请分别采用循环首次适应算法和最坏适应算法进行内存块的分配和回收,要求每次分配和回收后显示出空闲内存分区链的情况。 3、模拟算法的实现 3.1循环首次适应算法 3.1.1算法思路分析 该算法是首次适应算法的变种。 在分配内存空间时,不再每次从表头(链首)开始查找,而是从上次找到空闲区的下一个空闲开始查找,直到找到第一个能满足要求的的空闲区为止,并从中划出一块与请求大小相等的内存空间分配给作业。 该算法能使内存中的空闲区分布得较均匀。 为实现该算法,应设置一起始查找指针,用于指示下一次起始查询的空闲分区,并采用循环查找方式,即如果最后一个(链尾)空闲分区的大小仍不能满足要求,则返回到第一个空闲分区,比较大小是否满足,找到后,应调整起始查询指针。 动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。 另一种也是最常用的就是空闲链表,由于对分区的操作是动态的,所以很难估计数据结构所占用的空间,而且空闲区表会占用宝贵的系统空间,所以提出了空闲链表的概念。 其特点是用于管理分区的信息动态生成并和该分区在物理地址上相邻。 这样由于可以简单用两个空闲块之间的距离定位已分配空间,不仅节约了系统空间,而且不必维持已分配空间的信息。 定义一个结构体及其对象subHead实现内存的分配回收及分配表和空闲表的登记。 用最佳分配算法实现动态分配时,调用intcfirstFit(inttaskId,intsize)内存分配函数,设定循环条件查找最佳空闲分区,根据找到的空闲区大小和作业大小判断是整个分配给作业还是切割空闲区后再分配给作业,并在“内存分配表”和“空闲分区表”中作登记。 调用intfreeSubArea(inttaskId)函数实现内存的回收 3.1.2主要数据结构 本实验是要做一个模拟程序,来模拟动态分区算法的分配和回收过程,并不是真正的去分配和回收内存,所以采用的方法是不申请存储区,自己定义一块虚拟的存储区,对这块存储区进行模拟的分配和回收活动,分配和回收仅仅是对数据结构的修改而已。 #defineSIZE640//内存初始大小 enumSTATE{Free,Busy}; structsubAreaNode{ intaddr;//起始地址 intsize;//分区大小 inttaskId;//作业号 STATEstate;//分区状态 subAreaNode*pre;//分区前向指针 subAreaNode*nxt;//分区后向指针 } voidintSubArea(): 分配初始分区内存。 定义的结构体: structsubAreaNode。 记录分区的主要数据。 intfreeSubArea(inttaskId): 内存回收函数,该函数主要用于实现内存的回收,根据回收内存的位置对分区进行合并操作。 其中taskId为所需回收内存的作业号。 voidshowSubArea(): 显示空闲分区链情况。 包括起始地址,空间大小。 工作状态。 作业号。 3.1.3算法流程图 图3-1 3.1.4算法代码实现 #include #include #include #defineSIZE640//内存初始大小 #defineMINSIZE5//碎片最小值 enumSTATE{Free,Busy}; staticintss=0,ee=0,i=0; structsubAreaNode{ intaddr;//起始地址 intsize;//分区大小 inttaskId;//作业号 STATEstate;//分区状态 subAreaNode*pre;//分区前向指针 subAreaNode*nxt;//分区后向指针 }subHead; //初始化空闲分区链 voidintSubArea() {//分配初始分区内存 subAreaNode*fir=(subAreaNode*)malloc(sizeof(subAreaNode)); //给首个分区赋值
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 实验 报告