操作系统实验报告

时间:2024.4.20

淮 阴 工 学 院

实   验   报   告

__2012 _-__2013__学年 第__1__学期

 学    院___计算机工程学院__

 课程名称_____操作系统    __

 班    级_____软件1101_____

 学    号____1101305114_____

 姓    名_______王  祥______

 指导教师_______严云洋______

实验一:进程调度

1. 实验目的:

通过这次实验,加深对进程概念的理解,进一步掌握进程状态的转变、进程调度的策略及对系统性能的评价方法。

2. 实验内容:

设计程序模拟进程的轮转法调度过程。假设初始状态为:有n个进程处于就绪状态,有m个进程处于阻塞状态。采用轮转法进程调度算法进行调度(调度过程中,假设处于执行状态的进程不会阻塞),且每过t个时间片系统释放资源,唤醒处于阻塞队列队首的进程。

程序要求如下:

1).输出系统中进程的调度次序;

2).计算CPU利用率。

3. 实验环境:

硬件环境:Ghost XP SP3 纯净版 Y6.0  Pentium(R) Dual-Core CPU E6700 @ 3.20GHz 3.19 GHz, 1.96 GB 的内存物理地址扩展

软件环境:Microsoft Windows XP , Visual Studio 2008

4. 源代码:

#include <iostream>

#include <algorithm>

#include <queue>

using namespace std;

onst int MaxNum = 100;

struct Node{

     int index;

     int arriveTime;

     int rest;

};

bool NodeCmp(const Node& a,const Node& b)

{

     return a.arriveTime < b.arriveTime;

}

int n;  //进程数

int ArrivalTime[MaxNum];

int ServiceTime[MaxNum];

int PServiceTime[MaxNum];

int FinishTime[MaxNum];

int WholeTime[MaxNum];

double WeightWholeTime[MaxNum];

bool Finished[MaxNum];

double AverageWT,AverageWWT;

bool isEnterQue[MaxNum];

int cntTimes[MaxNum];

void init()

{

     memset(PServiceTime,0,sizeof(PServiceTime));

     memset(Finished,0,sizeof(Finished));

     memset(FinishTime,0,sizeof(FinishTime));

     memset(WholeTime,0,sizeof(WholeTime));

     memset(WeightWholeTime,0,sizeof(WeightWholeTime));

}

int sum(int array[],int n) 

{

     int sum=0;

     int i;

     for(i=0;i<n;i++)

     {

         sum += array[i];

     }

     return sum;

}

double sum(double array[],int n)

{

     double sum=0;

     int i;

     for(i=0;i<n;i++)

     {

         sum += array[i];

     }

     return sum;

}

void print()

{

     int i=0;

     cout<<"进程完成时间:";

     for(i=0;i<n;i++)

     {

         cout<<FinishTime[i]<<' ';

     }

     cout<<endl;

     cout<<"周转时间:";

     for(i=0;i<n;i++)

     {

         cout<<WholeTime[i]<<' ';

     }

     cout<<endl;

     cout<<"带权周转时间:";

     for(i=0;i<n;i++)

     {

         printf("%.2f ",WeightWholeTime[i]);

     }

     cout<<endl;

}

void SearchToEnterQue(queue<Node>& que,Node* pArr,int maxArrivalTime)

{

     int i;

     for(i=0;i<n;i++)

     {

         if(pArr[i].arriveTime>maxArrivalTime)

              break;

         if(isEnterQue[pArr[i].index]==false)

         {

              que.push(pArr[i]);

              isEnterQue[pArr[i].index] = true;

         }

     }

}

void Work(int q)

{

     init();

     memset(isEnterQue,0,sizeof(isEnterQue));

     memset(cntTimes,0,sizeof(cntTimes));

     Node* pNodeArr = new Node[n];

     int i;

     for(i=0;i<n;i++)

     {

         pNodeArr[i].index = i;

         pNodeArr[i].arriveTime = ArrivalTime[i];

         pNodeArr[i].rest = ServiceTime[i];

     }

     sort(pNodeArr,pNodeArr+n,NodeCmp);

    

     int totalTime = sum(ServiceTime,n);

     int time=pNodeArr[0].arriveTime;

     queue<Node> que;

     que.push(pNodeArr[0]);

     isEnterQue[pNodeArr[0].index]=true;

     Node cur;

     cout<<"================================================="<<endl;

     while(!que.empty())    {

         cur = que.front();

         que.pop();

        

         cntTimes[cur.index]++;

         if(cntTimes[cur.index]==1)

              printf("在%d时刻,进程%d开始执行。。。\n",time,cur.index);

         if(cur.rest > q)

         {

              time += q;

              cur.rest -= q;

         }

         else

         {

              time += cur.rest;

              Finished[cur.index]=true;

              FinishTime[cur.index] = time;

              cur.rest = 0;

              printf("在%d时刻,进程%d执行结束。\n",time,cur.index);

          }

         SearchToEnterQue(que,pNodeArr,time);

         if(cur.rest!=0)

              que.push(cur);

         if(que.empty())//若队列为空,则在time之后才达到的进程找最早到达的进程入队列

         {

              for(i=0;i<n;i++)

              {

                   if(isEnterQue[i]==false)//找到了

                   {

                       que.push(pNodeArr[i]);//入队列

                       time = pNodeArr[i].arriveTime;                    

break;

                   }

              }

         }

     }

     for(i=0;i<n;i++)

     {

         WholeTime[i] = FinishTime[i] - ArrivalTime[i];

         WeightWholeTime[i] = (double)WholeTime[i] / (double)ServiceTime[i];

     }

     AverageWT = (double)sum(WholeTime,n)/(double)n;

     AverageWWT=(double)sum(WeightWholeTime,n)/(double)n;     cout<<"================================================="<<endl;

     print();

     cout<<endl<<endl;  cout<<"================================================="<<endl;

     printf("平均周转时间:%.2f,平均带权周转时间:%.2f\n",AverageWT,AverageWWT);

     delete[] pNodeArr;

}

int main()

{

//   freopen("test.txt","rw",stdin);

     int q;//时间片大小

     int i;

     cout<<"输入进程数:";

     cin>>n;;

     cout<<"输入每个进程的到达时间:"<<endl;

     for(i=0;i<n;i++)

         cin>>ArrivalTime[i];

     cout<<"输入每个进程的服务时间:"<<endl;

     for(i=0;i<n;i++)

         cin>>ServiceTime[i];

     cout<<"输入时间片大小"<<endl;

     cin>>q;

     Work(q);

     return 0;

}

5. 实验结果: 

6. 试验分析和体会:

实验二  分区式存储管理

1. 实验目的:

通过这次实验,加深对内存管理的认识,进一步掌握内存的分配、回收算法的思想。

2. 实验内容:

设计程序模拟内存的动态分区法存储管理。内存空闲区使用自由链管理,采用最坏适应算法从自由链中寻找空闲区进行分配,内存回收时假定不做与相邻空闲区的合并。

假定系统的内存共640K,初始状态为操作系统本身占用64K。在t1时间之后,有作业A、B、C、D分别请求8K、16K、64K、124K的内存空间;在t2时间之后,作业C完成;在t3时间之后,作业E请求50K的内存空间;在t4时间之后,作业D完成。要求编程序分别输出t1、t2、t3、t4时刻内存的空闲区的状态。

3. 实验环境:

硬件环境:Ghost XP SP3 纯净版 Y6.0  Pentium(R) Dual-Core CPU E6700 @ 3.20GHz 3.19 GHz, 1.96 GB 的内存物理地址扩展

软件环境:Microsoft Windows XP , Visual Studio 2008

4. 源代码:

#include "stdafx.h"

#include<stdio.h>

#include<stdlib.h>

struct freelink

{

     int len, address;  // len为分区长度;address为分区起始地址

     struct freelink  * next;

};//内存占用区用链表描述,其结点类型描述如下:

struct busylink

{

     char name;   //  作业或进程名 name='S' 表示OS占用

     int len , address;

     struct  busylink *next;

} ;

//并设全程量:

struct  freelink   *free_head=NULL;     // 自由链队列带头结点)队首指针?       

struct  busylink   *busy_head=NULL, *busy_tail=NULL;   // 占用区队列队(带头结点)首指针             

                       // 占用区队列队尾指针

// 设计子函数:

void  start(void)   /* 设置系统初始状态*/

struct freelink * p;

struct busylink *q;

free_head=(struct  freelink*)malloc(sizeof(struct  freelink));

free_head->next=NULL;  // 创建自由链头结点

busy_head=busy_tail=(struct busylink*)malloc(sizeof(struct busylink));

busy_head->next=NULL;  // 创建占用链头结点

p=( struct freelink *)malloc(sizeof(struct freelink));

p->address=64;

p->len=640-64;  //(OS占用了K)

p->next=NULL;

free_head->next=p;

q=( struct  busylink *)malloc(sizeof(struct busylink));

q->name='S';  /* S表示操作系统占用 */

     q->len=64;  q->address=0;  q->next=NULL;

busy_head->next=q;  busy_tail=q;

}

void  requireMemo(char  name, int  require) /*模拟内存分配*/

{

     struct  freelink *w,*u,*v,*x,*y;

     struct busylink *p;

     x=free_head;

     y=free_head->next;

     while((y!=NULL) &&(y->len<require))  //找到第一个满足条件的空闲区

     {

         x=y;

         y=y->next;

     }

     if(y!=NULL)

     {

         p=(struct busylink*)malloc(sizeof(busylink));

         p->name=name;

         p->address=y->address;

         p->len=require;

         p->next=NULL;

         busy_tail->next=p; //把p插入到busy_head的尾部

         busy_tail=p;

         w=x->next;

         x->next=w->next;

         if(w->len==require)

         {

              free(w);

         }

         else

         {

              w->address=w->address+require;

              w->len=w->len-require;

              u=free_head;

              v=free_head->next;

              while((v!=NULL) && (v->len<w->len))//如果此结点还有多余,就此又重新插入到空闲区域链中(按照长度由小到大的次序排列)

              {

                   u=v;

                   v=v->next;

              }

              u->next=w;

              w->next=v;

         }

     }

     else

         printf("can't allocate!\n");

}

void  freeMemo(char name)  /* 模拟内存回收*/

{

     struct busylink *p,*q;

     struct freelink *w,*u,*v,*s1=NULL,*s2=NULL;

     int len,address;

     int flag1=1,flag2=1;

     p=busy_head->next;

     while((p!=NULL)&&(p->name!=name)) //找到要回收的结点

     {

         q=p;

         p=p->next;

     }

     if(p==NULL)

     {

         printf("%c is not exist\n",name);

     }

     else

     {

         if  (p==busy_tail)

              busy_tail=q;

         q->next=p->next;

         len=p->len;

         address=p->address;

         free(p);

        

         w=(struct freelink*) malloc(sizeof(freelink));

         w->len=len;

         w->address=address;

         u=free_head;

         v=free_head->next;

         while((v!=NULL) && (flag1==1 || flag2==1))  //归并算法

         {

              if((w->address==(v->address+v->len)) &&flag1) 

              {

                   s1=v;

                   u->next=s1->next;

                   w->address=v->address;

                   w->len+=v->len;

                  v=v->next;

                   flag1=0;

              }

             else if(((w->address+w->len)==v->address) &&flag2)

              {

                   s2=v;

                   u->next=s2->next;

                   w->len+=v->len;

                   v=v->next;

                   flag2=0;

              }

              else

              {

                   u=v;

                   v=v->next;

              }   

         }

         if(s1!=NULL)

              free(s1);

         if(s2!=NULL)

              free(s2);

         u=free_head;

         v=free_head->next;

    

         if(v!=NULL)

         {

              while((v!=NULL) && (v->len<w->len))

              {

                   u=v;

                   v=v->next;

              }

         }

              u->next=w;

              w->next=v;

     }

}

void  past(int  time)  /* 模拟系统过了时间time,用sleep(),或者用个空循环*/

{

    

         printf("时间%d后:\n",time);

}

void  printlink()  /* 输出内存空闲情况(自由链的结点)*/

{

     struct  freelink   *p;

     p=free_head->next;

     if(p==NULL)

         printf("无空闲区!\n");

     else

     {

         while(p!=NULL)

         {

         printf("首地址:%d\t长度:%d\n",p->address,p->len);

         p=p->next;

         }

     }

     printf("----------------------------------------\n");

    

}

void  printlink1()  /* 输出内存占用的情况*/

{

     struct  busylink   *p;

     p=busy_head->next;

     if(p==NULL)

         printf("无内存占有区!\n");

     else

     {

         while(p!=NULL)

         {

         printf("名字:%c\t首地址:%d\t长度:%d\n",p->name,p->address,p->len);

         p=p->next;

         }

     }

    

}

//   设计主函数:

int main()

{

     start();

     past(1);

     requireMemo('A',8);  requireMemo('B',16);

     requireMemo('C',64); requireMemo('D',124);

     printf("内存占用区为:\n");

     printlink1();

     printf("内存空闲区为:\n");

     printlink();

     past(2);

     freeMemo('C');

     printf("内存占用区为:\n");

     printlink1();

     printf("内存空闲区为:\n");

     printlink();

     past(3);

     requireMemo('E',50);

     printf("内存占用区为:\n");

     printlink1();

     printf("内存空闲区为:\n");

     printlink();

     return 0;

}

5. 实验结果:

6. 试验分析和体会:

首先,对链表又有进一步的理解,还有就是加深理解内存的分配与回收,分配与回收的策略,并掌握动态分区这种内存管理的具体实施方法。

   再者,就是在编程中遇到的困难,在编写归并程序首先是自己考虑问题不全面,写的程序就只顾及到一个结点,而没有实现有两个结点的情况,于是后来再加了一条else语句,就没有出现问题。还有一个问题就是将多余的结点free时也出现问题,加了一条if(s==NULL),成立就释放掉。一开始把free语句写在while循环内,一旦把找到的结点释放掉,则找不到下一个结点,也会出错,所以应该把free放到while循环外。

实验三  虚拟存储管理

1. 实验目的:

存储管理的主要功能之一是合理的分配空间。请求页式管理是一种常用的虚拟存储管

理技术。

本实验的目的是请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换方法。

2. 实验内容:

(1)通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成:

①、  50%的指令是顺序执行的;

②、  25%的指令是均匀分布在前地址部分;

③、  25%的指令是均匀分布在后地址部分。

具体的实施方法是:

①                 在[0,319]的指令地址之间随机选取一起点m;

②                 顺序 执行一条指令,即执行地址为m+1的指令;

③                 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’;

④                 顺序执行一条指令,其地址为m’+1;

⑤                 在后地址[m’+2,319]中随机选取一条指令并执行;

⑥                 重复上述步骤,直至执行320次指令。

(2)       将指令序列变换成页地址流

 设:①页面大小为1K;

②用户内存容量为4页到32页;

③用户虚存容量为32K;

在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:

第0条~第9条指令为第0页(对应的虚存地址为[0,9]);

第10条~第19条指令为第1页(对应的虚存地址为[10,19]);

.

第310条~第319条指令为第31页(对应的虚存地址为[310,319]);

按以上方式,用户指令可组成32页。

(3)       计算并输出下述各种算法在不同的内存容量下的命中率。

①     先进先出的算法(FIFO);

②     最近最少使用算法(LRR);

③     最佳淘汰法(OPT):先淘汰最不常用的页地址;

④     最少访问页面算法(LFR);

⑤     最近不经常使用算法(NUR)。

其中③和④为选择内容。

命中率=1-(页面失效次数)/(页地址流长度)

在本实验中,页地址流的长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不在内存的次数。

2、  随机数产生办法

关于随机书产生办法,可以使用系统提供函数rand(),分别进行初始化和产生随机数。例如:srand();语句可初始化的一个随机数;a[0]=10*rand()/32767*319+1;

a[1]=10*rand()/32767*a[0];

语句可用来产生a[0]与a[1]中的随机数。

3. 实验环境:

硬件环境:Ghost XP SP3 纯净版 Y6.0  Pentium(R) Dual-Core CPU E6700 @ 3.20GHz 3.19 GHz, 1.96 GB 的内存物理地址扩展

软件环境:Microsoft Windows XP , Visual Studio 2008

4. 源代码:

#define TRUE 1

#define FALSE 0

#define INVALID -1

#define NULL  0

#define  total_instruction  320     /*指令流长*/

#define  total_vp  32               /*虚页长*/

#define  clear_period  50           /*清周期*/

typedef struct                      /*页面结构*/

{

     int pn,pfn,counter,time;

}pl_type;

pl_type pl[total_vp];               /*页面结构数组*/

struct pfc_struct{                  /*页面控制结构*/

     int pn,pfn;

     struct pfc_struct *next;

};

typedef struct pfc_struct pfc_type;

pfc_type pfc[total_vp],*freepf_head,*busypf_head,*busypf_tail;

int diseffect,  a[total_instruction];

int page[total_instruction],  offset[total_instruction];

int  initialize(int);

int  FIFO(int);  /*先进先出法(Fisrt In First Out)*/

int  LRU(int); /*最近最久未使用(Least Recently Used)*/

int  LFU(int); /*最不经常使用法(Least Frequently Used)*/

int  NUR(int); /*最近未使用法(No Used Recently)*/

int  OPT(int); /*最佳置换算法(Optimal)*/

/*主函数*/

int main( )

{

  int s,i,j;

  srand(10*getpid());              /*由于每次运行时进程号不同,故可用来作为初始化随机数队列的“种子”*/

s=(float)319*rand( )/32767/32767/2+1;  //

for(i=0;i<total_instruction;i+=4) /*产生指令队列*/

{

     if(s<0||s>319)

     {

       printf("When i==%d,Error,s==%d\n",i,s);

       exit(0);

     }

     a[i]=s;                            /*任选一指令访问点m*/

     a[i+1]=a[i]+1;                     /*顺序执行一条指令*/

     a[i+2]=(float)a[i]*rand( )/32767/32767/2; /*执行前地址指令m' */

     a[i+3]=a[i+2]+1;                   /*顺序执行一条指令*/

     s=(float)(318-a[i+2])*rand( )/32767/32767/2+a[i+2]+2;

     if((a[i+2]>318)||(s>319))

       printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s);

}

for (i=0;i<total_instruction;i++) /*将指令序列变换成页地址流*/

{

     page[i]=a[i]/10;

     offset[i]=a[i]%10;

}

for(i=4;i<=32;i++)   /*用户内存工作区从个页面到个页面*/

{

      printf("---%2d page frames---\n",i);

      FIFO(i);

      LRU(i);

      LFU(i);

      NUR(i);

      OPT(i);

}

   return 0;

}

int initialize(total_pf)              /*初始化相关数据结构*/

int total_pf;                          /*用户进程的内存页面数*/

{int i;

diseffect=0;

for(i=0;i<total_vp;i++)

{

       pl[i].pn=i;

       pl[i].pfn=INVALID;        /*置页面控制结构中的页号,页面为空*/

       pl[i].counter=0;

       pl[i].time=-1;         /*页面控制结构中的访问次数为,时间为-1*/

}

for(i=0;i<total_pf-1;i++)

{

       pfc[i].next=&pfc[i+1];

       pfc[i].pfn=i;

}   /*建立pfc[i-1]和pfc[i]之间的链接*/

pfc[total_pf-1].next=NULL;

pfc[total_pf-1].pfn=total_pf-1;

freepf_head=&pfc[0];         /*空页面队列的头指针为pfc[0]*/

return 0;

}

int FIFO(total_pf)              /*先进先出算法*/

int total_pf;                    /*用户进程的内存页面数*/

{

     int i,j;

     pfc_type *p;

     initialize(total_pf);         /*初始化相关页面控制用数据结构*/

     busypf_head=busypf_tail=NULL; /*忙页面队列头,队列尾链接*/

     for(i=0;i<total_instruction;i++)

   {

   if(pl[page[i]].pfn==INVALID)   /*页面失效*/

     {

      diseffect+=1;                  /*失效次数*/

      if(freepf_head==NULL)         /*无空闲页面*/

       {

         p=busypf_head->next;

         pl[busypf_head->pn].pfn=INVALID;

         freepf_head=busypf_head;  /*释放忙页面队列的第一个页面*/

         freepf_head->next=NULL;

         busypf_head=p;

       }

        p=freepf_head->next;         /*按FIFO方式调新页面入内存页面*/

        freepf_head->next=NULL;

        freepf_head->pn=page[i];

        pl[page[i]].pfn=freepf_head->pfn;

     if(busypf_tail==NULL)

        busypf_head=busypf_tail=freepf_head;

     else

    {

      busypf_tail->next=freepf_head;  /*free页面减少一个*/

      busypf_tail=freepf_head;

     }

        freepf_head=p;

     }

}

printf("FIFO:%6.4f\n",1-(float)diseffect/320);

return 0;

}

5. 实验结果:

6. 试验分析和体会:

更多相关推荐:
操作系统实验报告 完全版

《计算机操作系统》实验报告班级:姓名:学号:实验一进程控制与描述一、实验目的通过对Windows2000编程,进一步熟悉操作系统的基本概念,较好地理解Windows2000的结构。通过创建进程、观察正在运行的进…

操作系统实验报告

操作系统实验报告实验名称理解UNIXLINUXShell及UNIX的进程树成绩专业班级计科姓名学号联系电话实验日期20xx年12月5日实验报告日期20xx年12月5日一实验名称理解UNIXLINUXShell及...

操作系统实验报告

目录实验一进程的创建2实验二进程控制3实验三进程的管道通信4实验四消息通信6实验五进程调度算法8实验六FIFO页面置换算法12实验七LRU页面置换算法14实验八磁盘调度18实验一进程的创建1一实验目的编写一段程...

操作系统实验报告

操作系统实验报告学号姓名班级实验一实验报告实验名称并发程序设计实验1实验目的掌握在程序中创建新进程的方法观察并理解多道程序并发执行的现象实验原理fork建立子进程子进程得到父进程地址空间的一个复制返回值成功时该...

计算机操作系统课程设计报告

《操作系统原理》实验报告院(部):管理工程学院专业:信息管理与信息系统实验项目:实验一二三五班级:信管102姓名:学号:目录引言.........................................…

操作系统课程设计实验报告

操作系统课程设计实验报告姓名学号班级地点20xx年月日任务说明共完成四个任务任务一IO系统调用开销比较任务二实现一个简单的shell任务三进程线程同步任务四文件内容的并行搜索其中任务一完成了标准c和unix下的...

操作系统实验报告

郑州航空工业管理学院计算机科学与应用系课程设计报告操作系统原理操作系统课程设计目录1题目简述22需求分析221设计思想222要求323任务324运行环境325开发工具33概要设计与详细设计331系统流程图332...

操作系统实验报告

学号操作系统实验报告学院专业班级姓名实验成绩评阅教师评阅日期实验1进程调度模拟实验一实验目的1理解进程的概念熟悉进程的组成2用高级语言编写和调试一个进程调度程序以加深对进程调度算法的理解二实验准备1几种进程调度...

操作系统实验报告一

计算机操作系统实验报告一姓名学号实验环境MicrosoftVisualC60实验目的进程是操作系统最重要的概念之一进程调度又是操作系统核心的主要内容本实习要求学生独立地用高级语言编写和调试一个简单的进程调度程序...

操作系统实验报告

计算机操作系统实验二进程调度1目的和要求通过这次实验理解进程调度的过程进一步掌握进程状态的转变进程调度的策略进一步体会多道程序并发执行的特点并分析具体的调度算法的特点掌握对系统性能的评价方法2实验内容阅读教材计...

操作系统实验报告

操作系统上机实验报告班级学号姓名实验地点E区203实验时间20xx92620xx125实验一进程的建立实验目的创建进程及子进程在父子进程间实现进程通信实验软硬件环境Linux实验内容创建进程并显示标识等进程控制...

操作系统实验报告

实验二进程管理一进程的创建实验思考题1系统是怎样创建进程的解linux系统创建进程都是用fork系统调用创建子进程2当首次调用新创建进时其入口在哪里解由fork系统调用创建的新进程被称为子进程该函数被调用一次但...

操作系统实验报告(38篇)