1、资料内容仅供您学习参考,如有不当之处,请联系改正或者删除。 东莞理工学院 操作系统课程设计报告 学 院: 计算机学院 专 业 班 级: 13软件工程1班 学号 姓名 评价 提交时间: /9/14 指导教师评阅意见: . 项目名称: 进程与线程管理功能 一、 设计目的 用语言来模拟进程和线程管理系统, 加深对进程和线程的
2、理解, 掌握对进程和线程各种状态和管理的算法原理。 二、 环境条件 系统: WindowsXP、 VMWare、 Ubuntu Linux 语言: C/C++ 开发工具: gcc/g++、 Visual C++ 6.0 三、 设计内容 1. 项目背景 计算机的硬件资源有限, 为了提高内存的利用率和系统的吞吐量, 就要根据某种算法来管理进程和线程的状态从而达到目的。 进程与线程管理功能完成基于优先级的抢占式线程调度功能, 完成进程虚拟内存管理功能。 进程与线程管理功能 基本要求: 完成基于优先级的抢占式线程调度功能, 完成进程虚拟内存管理功能。 提高要求: ( 增加1
3、项就予以加分) (1) 实现多种线程调度算法; (2)经过”公共信箱”进行通信的机制, 规定每一封信的大小为128字节, 实现两个用户进程之间经过这个”公共信箱”进行通信。 (3) 实现多用户进程并发的虚拟内存管理功能。 (4) 实现用户进程间通信功能, 并用生产者/消费者问题测试进程间通信功能的正确性。 (5) 实现改进型Clock页面置换算法。 (6) 实现Cache功能, 采用FIFO替换算法。 2. 扩展内容 实现多种线程调度算法:时间片轮转调度算法 四、 人员分工 优先级调度算法: 钟德新, 莫友芝 时间片轮转调度算法: 张德华, 袁马龙 设计报告由小组
4、队员共同完成。小组成员设计的代码分工如下:
钟德新编写的代码: void Prinft(){
PCB *p;
system("cls");//清屏
p=run; //运行队列
if(p!=NULL)
{
p->next=NULL;
}
cout<<"当前正在运行的进程: "<
5、t\t"<
6、t"<
7、"\t\t"<
8、 S2 = S1; while(S1!=NULL) { if(S1->pri >= p->pri) //判断优先级大小 { S2 = S1; //置换位置 S1 = S1->next; }else{ break; //跳出循环 } } if(S2->pri >= p->pri) { S2->next = p; p->next = S1; }else{ p->next = ready; ready = p;
9、 } } } 这是程序优先级排序的函数, 也是优先级调度算法的核心思想函数, 对程序的优先级经过指针进行排序, 再将队首的程序调入运行队列, 经过置换的方法, 将运行队列队首即占用CPU的程序调入就绪队列, 如此循环直至所有程序终止为止。 莫友芝编写的代码: void priority() { run = ready; ready = ready->next; run->state = "运行"; while(run!=NULL) /*当运行队列不空时, 有进程正在运行*/ { Dtime(3);//调用延时函数, 延时3秒 run->run
10、time=run->runtime+1; //运行时间+1 run->needOftime=run->needOftime-1; //完成需要时间-1 run->pri=run->pri-1; /* //优先级-1每运行一次优先数降低1个单位*/ if(run->needOftime==0) /*如所需时间为0将其插入完成队列*/ { run->state = "完成"; run->next = finish; finish = run; run=NULL; /*运行队列头指针为空*/ if(ready!=
11、NULL) /*如就绪队列不空*/ { run = ready; run->state = "运行"; ready = ready->next; } }else if( (ready!=NULL)&&(run->pri < ready->pri) ){ //就绪队列不为空, 就绪队列队首优先级大于运行队列队首 run->state="就绪"; insert(run); //运行中的进程重新比较优先级大小 run = ready; //对队列队首的进程调入CPU run->state = "运行
12、"; ready = ready->next; } Prinft(); /*输出进程PCB信息*/ } } 这是程序运行时的实时程序, 经过循环的方法在程序等候3秒后, 调用德新设计的优先级排序算法, 进行排序。 void CTProcessOfPri()//创立进程 { PCB * Node; string c[5]={"P1","P2","P3","P4","P5"}; //模拟设计5条进程 srand((int)time(0)); //设置随机种子 for(int j = 0;j < 5; j++
13、) { Node = new PCB; if(Node==NULL) { return; }else{ Node->procname=c[j]; //为进程名赋值 Node->needOftime=1+(int)(15.0*rand()/(RAND_MAX+1.0));//为进程随机分配占用CPU时间. Node->runtime = 0; //为运行时间赋值 Node->state ="就绪"; //设置初始状态为”就绪”状态 Node->pri =1+(int)
14、20.0*rand()/(RAND_MAX+1.0)); //为进程随机分配优先数.
}
insert(Node); //出入就行队列
}
}
随机创立5个模拟程序, 为其赋上初值后, 调用优先级排序函数, 进行第一次排序
张德华编写的程序代码: void insert(PCB *p){ //时间片插入函数
if(start->next==NULL){
PCB *q=start;
if(p->Arrive_time
15、ext=q; q->next=NULL; end=q; }else{ q->next=p; p->next=NULL; end=p; } }else{ PCB *q=start; PCB *s=start->next; while(s!=NULL){ if(q->Arrive_time > p->Arrive_time){ p->next=q; start=p; return; }else{
16、if(s->Arrive_time > p->Arrive_time){ q->next=p; p->next=s; return; }else{ q=q->next; s=s->next; } } } s->next=p; end=p; } } 这个是时间片插入函数, 也是轮转调度模拟程序的核心函数, 首先对到达时间进行排序, 将队首调入CPU后, 运行时间片的时间后, 调入就绪队列队尾, 等候下一次的资源.
17、 void firstin(){ //将就绪队列的第一个进程放入运行队列 run=start; run->State='W'; //改变其状态 start=start->next; } 模拟占用CPU的函数 void show(PCB *p) //输出函数 { cout<<"进程名"<<"\t"<<"到达时间"<<"\t"<<"剩余时间"<<"\t"<<"状态\n"; // if(run!=NULL) //如果运行指针不为空,就输出当前正在运行的进程的PCB { cout<<
18、p->name<<"\t"<
19、nish=NULL; //完成队列头指针 run=NULL; //运行队列指针 cout<<"请输入时间片长度: "; cin>>Time_piece; for(int i=1;i<=N;i++){ //输入进程名字和所需时间,创立进程的PCB p=(PCB *)malloc(sizeof(PCB)); cout<<"请输入第"<>p->name; cout<<"预计运行的时间:"; cin>>p->Need_time;
20、cout<<"到达时间:"; cin>>p->Arrive_time; Cpu_time=0; p->Count=0; //计数器 p->State='W'; //进程的初始状态设为就绪'W' p->Time_piece=Time_piece; //时间片的初始值 if(start!=NULL){ insert(p); //若就绪队列不为空,将其插入就绪队列 }else{ //创立就绪队列的第一个PCB p->next=start; start=p;
21、 //头指针
end=p; //尾指针
}
}
cout<
22、目, 程序名称, 运行时间等, 在调用德华设计的排序函数进行排序, 调入队列中
void roundrobin(){ //时间片算法函数
int m=0;
while(run!=NULL){
if(run->Arrive_time>Cpu_time){
Cpu_time=Cpu_time+1; //每运行一次cputime加一
}else{
if(m==0){
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<
23、\n\n"; m++; } run->Need_time=run->Need_time-1; //每运行一次needtime减一 if(run->Need_time!=0) show(run); Cpu_time=Cpu_time+1; //每运行一次cputime加一 run->Count=run->Count+1; //每运行一次计数器count加一 if(run->Need_time==0){ //若运行完后 run->next=finish; f
24、inish=run; //将其插入完成队列头部
run->State='F'; //将其状态改为完成态"F"
show(run);
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<
25、~~~~~~~~~~~~进程"<
26、 //将就绪队列的第一个进程投入运行
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<
27、的运行过程是系统进行资源分配和调度的一个独立单位。另有一种定义方法是”程序在处理器上的执行”。为了模拟的方便, 本设计采用这种定义。简单地说, 进程包括三种状态: 运行状态、 就绪状态、 完成状态 优先级调度算法: 按照进程的优先级大小来调度, 是高优先级进程得到优先的处理的调度策略, 可使用非抢占或可抢占两种策略 用C++模拟设计一个进程模拟类class PCB{ public: string procname;//进程名 int pri;//进程优先数 string state;//进程状态 int runtime;//进程已运行CPU时间 int nee
28、dOftime;//还需要时间 PCB *next;//指针 }; 来记录进程的基本信息, 如进程名称, 优先级, 进程状态, 进程运行时间, 进程所需时间 再设计模拟进程所需要的各种算法, 运行调试结果 时间片轮转调度算法: 是一种最古老, 最简单, 最公平且使用最广的算法。每个进程被分配一时间段, 称作它的时间片, 即该进程允许运行的时间. 如果在时间片结束时进程还在运行, 则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束, 则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表, 当进程用完它的时间片后, 它被移到队列的末尾. 用C语
29、言模拟设计一个类typedef struct node { char name[10]; //进程名 int Time_piece; //时间片 int Need_time; //还需要的时间 int Count; //计数器 char State; //进程的状态 struct node *next; //链指针 int Arrive_time; //到达时间 }PCB; 用这个类根据算法的基本思想来设计程序, 模拟算法的运行情况 优先级抢占式调度算法: ( 过程图) 时间片轮转调度算法:( 过程图) 六、 运行
30、结果 优先级抢占式: 时间片轮转调度算法: 七、 结果分析 程序的结果很好体现的进程运行的优先级处理, 对于优先级高的程序, 采用抢占式, 分配程序CPU使用, 优先级较低的进入就绪队列等待CPU资源 而时间片轮转调度算法也很好的实行预期情况, 程序进入CPU运行时间片长度的时间后, 调入就绪队列队尾, 完成则进入完成队列。队首调入CPU, 占用资源, 循环直到所有程序都进入就绪队列. 八、 设计总结 1.设计基本实现了我们小组想要的功能和预测情况, 虽然中间关于指针的使用我们做了许多的调试, 可是我们还是做出来了。 2.然后就是进程算法的调用过程和知识, 发现
31、自己对知识的遗忘程度有点大, 边做边补, 实验结束的会后发现自己的知识巩固了不少。对操作系统的了解也更加深入了。
3.和队友合作然后团队意识有一定的提高
附录:
优先级抢占式调度算法:
///////////////////////////优先级抢占式线程调度算法/////////////////////////
#include "stdlib.h"
#include
32、PCB { public: string procname;//进程名 int pri;//进程优先数 string state;//进程状态 int runtime;//进程已运行CPU时间 int needOftime;//还需要时间 PCB *next;//指针 }; PCB *run = NULL; //运行队列头指针 PCB *ready = NULL;//就绪队列头指针 PCB *finish = NULL;//完成队列头指针 /////////////////////////////////延时函数, 模拟CPU占用时间/
33、////////////////////////////
void Dtime(int t){ //此代码块参考网上资料
time_t current_time;
time_t start_time;
time(&start_time);
do{
time(& current_time);
}while((current_time-start_time) 34、id Prinft(){
PCB *p;
system("cls");//清屏
p=run; //运行队列
if(p!=NULL)
{
p->next=NULL;
}
cout<<"当前正在运行的进程: "< 35、dOftime<<"\t\t"< 36、< 37、i<<"\t"< 38、ady;
S2 = S1;
while(S1!=NULL)
{
if(S1->pri >= p->pri) //判断优先级大小
{
S2 = S1; //置换位置
S1 = S1->next;
}else{
break; //跳出循环
}
}
if(S2->pri >= p->pri)
{
S2->next = p;
p->next = S1;
}else{
p->next = ready;
read 39、y = p;
}
}
}
//////////////////////////实时运行函数///////////////////////////////
void priority()
{
run = ready;
ready = ready->next;
run->state = "运行";
while(run!=NULL) /*
当运行队列不空时, 有进程正在运行
*/
{
Dtime(3);//调用延时函数, 延时3秒
run->runtime=run->runtime+1; //运行时间+1
run- 40、>needOftime=run->needOftime-1; //完成需要时间-1
run->pri=run->pri-1; /* //优先级-1
每运行一次优先数降低1个单位
*/
if(run->needOftime==0) /*
如所需时间为0将其插入完成队列
*/
{
run->state = "完成";
run->next = finish;
finish = run;
run=NULL; /*
运行队列头指针为空
*/
if(ready!=NULL) /*
如就 41、绪队列不空
*/
{
run = ready;
run->state = "运行";
ready = ready->next;
}
}else if( (ready!=NULL)&&(run->pri < ready->pri) ){ //就绪队列不为空, 就绪队列队首优先级大于运行队列队首
run->state="就绪";
insert(run); //运行中的进程重新比较优先级大小
run = ready; //对队列队首的进程调入CPU
run->s 42、tate = "运行";
ready = ready->next;
}
Prinft(); /*
输出进程PCB信息
*/
}
}
void CTProcessOfPri()//创立进程
{
PCB * Node;
string c[5]={"P1","P2","P3","P4","P5"}; //模拟设计5条进程
srand((int)time(0)); //设置随机种子
for(int j = 0;j < 5; j++)
{
Node = new PC 43、B;
if(Node==NULL)
{
return;
}else{
Node->procname=c[j]; //为进程名赋值
Node->needOftime=1+(int)(15.0*rand()/(RAND_MAX+1.0)); //为进程随机分配占用CPU时间.
Node->runtime = 0; //为运行时间赋值
Node->state ="就绪"; //设置初始状态为”就绪”状态
Node->pri =1+(int)(20.0*rand() 44、/(RAND_MAX+1.0)); //为进程随机分配优先数.
}
insert(Node); //出入就行队列
}
}
void main()
{
cout<<"*******************************************"< 45、etchar();
CTProcessOfPri(); //新建进程
Prinft(); //调用界面输出函数
cout< 46、 node {
char name[10]; //进程名
int Time_piece; //时间片
int Need_time; //还需要的时间
int Count; //计数器
char State; //进程的状态
struct node *next; //链指针
int Arrive_time; //到达时间
}PCB;
//run为当前运行进程指针,s 47、tart为就绪队列头指针
//end为就绪队列尾指针,finish为完成队列头指针
PCB *run,*start,*end,*finish;
int N; //进程个数
int Cpu_time;//需要的CPU时间
void insert(PCB *p){ //时间片插入函数
if(start->next==NULL){
PCB *q=start;
if(p->Arrive_time 48、
q->next=NULL;
end=q;
}else{
q->next=p;
p->next=NULL;
end=p;
}
}else{
PCB *q=start;
PCB *s=start->next;
while(s!=NULL){
if(q->Arrive_time > p->Arrive_time){
p->next=q;
start=p;
return;
}else{
if(s->Ar 49、rive_time > p->Arrive_time){
q->next=p;
p->next=s;
return;
}else{
q=q->next;
s=s->next;
}
}
}
s->next=p;
end=p;
}
}
void insert2(PCB *p){
end->next=p; //将新的PCB插入在当前就绪队列的尾
end=p;
p->nex 50、t=NULL;
}
void show(PCB *p) //输出函数
{
cout<<"进程名"<<"\t"<<"到达时间"<<"\t"<<"剩余时间"<<"\t"<<"状态\n"; //
if(run!=NULL) //如果运行指针不为空,就输出当前正在运行的进程的PCB
{
cout<






