操作系统实验报告

时间:2024.4.8

计算机操作系统

实验二   进程调度

1.目的和要求

通过这次实验,理解进程调度的过程,进一步掌握进程状态的转变、进程调度的策略,进一步体会多道程序并发执行的特点,并分析具体的调度算法的特点,掌握对系统性能的评价方法。

2.实验内容

阅读教材《计算机操作系统》第二章和第三章,掌握进程管理及调度相关概念和原理。

编写程序模拟实现进程的轮转法调度过程,模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。假设初始状态为:有n个进程处于就绪状态,有m个进程处于阻塞状态。采用轮转法进程调度算法进行调度(调度过程中,假设处于执行状态的进程不会阻塞),且每过t个时间片系统释放资源,唤醒处于阻塞队列队首的进程。

程序要求如下:

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

2)计算CPU利用率。

3.实验环境

Windows操作系统、VC++6.0  C语言

4.设计思想

每个进程有一个进程控制块( PCB—type)表示。进程控制块可以包含如下信息:进程名(pid),需要运行时间(cpu—time),进程状态(state)等等。进程的运行时间以时间片为单位进行计算。

每个进程的状态可以是执行 2,就绪 1、阻塞0。就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的运行时间减1,然后把它插入就绪队列尾部等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。当就绪队列的进程全都完成以后将阻塞进程队首进程插入到就绪队列尾部以便下次进行调用,反复直到阻塞队列为空,进程全部执行完成则退出。

5.源程序

 #include <stdio.h>

#include <stdlib.h>

struct  PCB_type

{

     int  pid ;     //进程名

     int   state ;    //进程状态  2--表示"执行"状态1--表示"就绪"状态 0--表示"阻塞"状态

     int  cpu_time ;  //运行需要的CPU时间(需运行的时间片个数)

};

struct  QueueNode{

             struct  PCB_type   PCB;

             struct  QueueNode  *next;

};

//并设全程量:

struct  QueueNode  *ready_head=NULL,     //ready队列队首指针

                   *ready_tail=NULL ,   //ready队列队尾指针

                   *blocked_head=NULL,   //blocked队列队首指针

                   *blocked_tail=NULL;     //blocked队列队尾指针

int static use_cpu,unuse_cpu;

/*定义进程的数目*/ 

//读入假设的数据,设置系统初始状态

void start_state()

 {

   int m,n,i;

   struct  QueueNode  *p;

  

   printf("输入就绪状态进程和阻塞状态进程个数 n,m:");

   scanf("%d%d",&n,&m);

   printf("就绪进程状态\n");

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

   p->next=NULL;

   ready_head=ready_tail=p;

  

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

   {

     struct  QueueNode  *p;

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

        p->next=NULL;

        printf("Enter %d process pid:",i+1);

        scanf("%d",&p->PCB.pid);

        printf("Enter %d process cpu_time:",i+1);

        scanf("%d",&p->PCB.cpu_time);

        p->PCB.state=1;

        ready_tail->next=p;

        ready_tail=p;

   }

   p=ready_head->next;

    i=1;

       printf("\n");

       while(p)

       {

       printf("第%d个进程:%d  %d和%d\n",i,p->PCB.pid,p->PCB.state,p->PCB.cpu_time);

      

              p=p->next;

              i++;

       }

   printf("阻塞进程状态");

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

   p->next=NULL;

   blocked_head=blocked_tail=p;

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

   {

     struct  QueueNode  *p;

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

        p->next=NULL;

        printf("Enter %d process pid:",i+1);

        scanf("%d",&p->PCB.pid);

        printf("Enter %d process cpu_time:",i+1);

        scanf("%d",&p->PCB.cpu_time);

        p->PCB.state=0;

        blocked_tail->next=p;

        blocked_tail=p;

   }

    p=blocked_head->next;

    i=1;

       printf("\n");

       while(p)

       {

       printf("第%d个进程:%d  %d和%d\n",i

,p->PCB.pid,p->PCB.state,p->PCB.cpu_time);

              p=p->next;

              i++;

       }

 }

 //模拟调度

void dispath()

{

  struct  QueueNode  *p;

       int x=0,t;

    printf("输入时间片t:");

       scanf("%d",&t);

       use_cpu=0;

       unuse_cpu=0;

       while(ready_head!=ready_tail || blocked_head!=blocked_tail)

       {

              if (ready_head!=ready_tail)

              {

                     p=ready_head->next;

                     ready_head->next=p->next;

                     p->next=NULL;

          if(ready_head->next==NULL)

                       ready_tail=ready_head;

                 p->PCB.state =2;

           printf("进程%d\n",p->PCB.pid);

                     p->PCB.cpu_time--;

                     use_cpu++;

                     if (p->PCB.cpu_time>0)

                     {

                            p->PCB.state =1;

                            ready_tail->next =p;

                            ready_tail=p;

                     }

                     else

                     {

              printf("进程%d已完成\n",p->PCB.pid);

                            free(p);

                     }

              }

              else

              {

                     unuse_cpu++;

              }

              x++;

    if(blocked_head!=blocked_tail && x==t)

              {

                     p=blocked_head->next;

                     blocked_head->next=p->next;

                     if(blocked_head->next==NULL)

                            blocked_tail=blocked_head;

                     //p->next=NULL;

                     ready_tail->next=p;

                     ready_tail=p;

            p->next=NULL;

                     x=0;

              }

       }

         printf("%d\n",unuse_cpu);

         printf("%d\n",use_cpu);

}

//计算CPU利用率

void calculate()

 {     

         double f;

        f=(double)use_cpu/use_cpu+unuse_cpu;

     printf("PCB的利用率为%lf",f);

 } 

void main()

{

     start_state();

     dispath();

     calculate();

}  

6.实例运行结果

7.实验总结

    这是第一次操作系统实验,用c语言编写模拟进程调度算法。由于c语言学了很长时间了,好多东西都忘了,所以最初在实验室的两个小时都毫无头绪,尽管老师已经给了一些代码,还把主要地方的流程图给了我们,还是觉得有难度。许老师看我们毫无进展,就集中给我们讲解了一下,一步步告诉我们怎么写,听完老师的讲解,自己也能回忆起一些c的知识,老师讲完后自己在开始写就觉得轻松了许多。通过操作系统实验让我认识到自己知识掌握的还不够牢靠,学过的知识不能灵活的运用,以后再学习过程中一定不要丢三落四,学过的知识还是要多巩固。希望下次实验可以做的更好。

实验三  可变分区存储管理

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.实验环境

Windows操作系统、VC++6.0

C语言

4.设计思想

   首先定义自由链和占用链两个链表结点,当申请内存分配时,自由链释结点刚好等于要申请的内存时直接分配,大于时剪切满足要求的分配;并将结点插入到占用链尾部,并修改尾部指针。作业完成释放内存时,先在占用链表中找到要释放的内存地址,修改相邻结点指针,再在自由链中寻找适合释放的内存大小的位置并插入进去。主要子函数有模拟分配函数和模拟回收函数,并在主函数中调用。

5.源程序

#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占用了64K)

    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 busylink *p;

       struct freelink *u,*v,*w;

       if(free_head->next->len>=require)

       {

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

       p->name=name;

       p->address=free_head->next->address;

       p->len=require;

          p->next=NULL;

       busy_tail->next=p;

          busy_tail=p;

       w=free_head->next;

       free_head->next=w->next;

          if(w->len==require)

             free(w);

       else //为w寻找合适的位置插入

          {

                 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");

}

/* 模拟内存回收*/

void  freeMemo(char name)

       struct busylink *q,*p;

       struct freelink *u,*w,*v;

       int address,len;

    q=busy_head;

    p= busy_head->next;

       while(p!=NULL&&p->name!=name)

       {

              q=p;

              p=p->next;

       }

       if(p==NULL)

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

    else

       {

              if(p==busy_tail)  

                     busy_tail=q;

           q->next=p->next;

        len=p->len;

              address=p->address;

              free(p);

     //在自由链中为p寻找合适的位置插入

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

      w->len=len;

      w->address=address;

      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;

       }

/* 模拟系统过了time 时间*/

void  past(int  time)

{

    printf("系统过了%d时间\n",time);

}

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

void  printlink()

{  

       struct freelink *p;

       int len=0;

       p=free_head->next;

    printf("此时空闲区状态:起始地址为%d\n",free_head->next->address);

       while(p!=NULL)

       {

              len+=p->len;

              p=p->next;

       }

    printf("此时内存的空闲量%d\n",len);

void  printlink2()

{   

       struct busylink *p;

       int len=0;

       p=busy_head->next;

    printf("此时占用区状态:起始地址为%d\n",busy_head->next->address);

       while(p!=NULL)

       {

              len+=p->len;

              p=p->next;

       }

    printf("此时内存的占用量%d\n",len);

       printf("\n");

}

void main()

{

  start();

  printlink();

  printlink2();

  past(1);

  requireMemo('A',8);

  requireMemo('B',16);

  requireMemo('C',64);

  requireMemo('D',124);

  printlink();

  printlink2();

  past(2);

  freeMemo('C');

  printlink();

  printlink2();

  past(3);

  requireMemo('E',50);

  printlink();

  printlink2();

  freeMemo('D');

  printlink();

  printlink2();

}

6.运行结果

    

7.实验总结

这次实验做起来相对比较轻松,一方面老师上课时将主要思想详细讲解了一遍,实验指导书上流程图也相对比较详细,另一方面,由于上次实验,自己对C语言的一些知识点也回忆起来不少,和上次一样,也主要涉及链表和指针,参考流程图很快便将代码写完了。但调试却花了一定的时间,由于开始在写输出内存空闲量和占用量时将输出语句直接写成printf(“空闲区空闲量为%d:”,free_head—>next—>len)运行后总觉得结果有问题,后来自己仔细想想又动手画一画觉得这里出现了问题,应该用循环语句将所有结点的内存大小相才行,语句改好后再运行,结果就对了。从这次实验,我觉得调试的过程是不简单的,但却很有意义,自己在调试过程中可以进一步了解自己的程序,把自己当电脑来一步步执行自己的程序,便可以很快找出问题所在。虽然是模拟分区存储管理,但通过这个实验也让自己对内存的分配与回收有了更深的了解。

实验四   操作系统存储管理实验

一、实验目的:

1、通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法。 

2、通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。  

二、实验环境:

VC 6.0++

三、实验内容

1、设计页面置换程序,模拟实现下面三种页面置换算法:

 FIFO、LRU、OPT算法设计一个请求页式存储管理方案。

2、设计一个可变式分区分配的存储管理方案。并模拟实现分区的分配和回收过程。 实现下面三种算法:

首次适应算法 ,最佳适应算法 ,最差适应算法

四、实验设计原理

1、页式存储系统打破存储分配的连续性,使得一个程序的逻辑地址空间可以分布在若干个离散的内存块上,从而达到充分利用内存,提高内存效率的目的。

页式存储系统将内存分为等长的若干区域,每个区域即一个页面。在对用户程序进行分配时,由系统调用页面置换算法对程序地址进行分配。常用页面置换算法有如下几种:

理想页面(OPT)置换算法:发生缺页时,有些页面在内存中将很快被访问,而其他页可能要到10、100或1000条指令后才被访问,对每个页面首次访问前要执行的指令数进行标记,置换掉最大的标记数页面。

先进先出(FIFO)置换算法:发生缺页时,总是选择最先装入的页面调出。

最近最少使用(LRU)置换算法:发生缺页时,总是选择距离现在最长时间没有使用的页面调出,而将使用过的页面放在最近位置。

2、分区分配

分区管理是能满足多道程序运行的最简单的存储管理方案。其基本思想是把内存划分成若干个连续区域,成为分区,每个分区装入一个运行程序。分区的方式可以归纳成固定分区和可变分区。

五、算法设计与流程

程序设计流程图如下:

1、页面置换算法流程图:

1、页面置换算法程序设计如下:

#include<iostream.h>

#define  M  40

#define  N  10//可用内存页面

struct Pro//页面结构体

{

    int num;

    int time;

};

int Input(int m, Pro p[])

{  

    cout<<"请输入实际页数:";

    do

    {

           cin>>m;

           if(m>M)  cout<<"数目太多,请重试"<<endl;

           else break;

    }while(1);

    cout<<endl<<"请输入各页面号"<<endl;

        for(int i=0;i<m;i++)

    {

           cin>>p[i].num;

           p[i].time=0;

    }

    return m;

}

void Print(Pro *page, int n)//打印当前的页面

{

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

           cout<<page[i].num<<"  ";

    cout<<endl;

}

int Search(int e, Pro *page, int n)//在内存页面中查找

{

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

           if(e==page[i].num)

                  return i;

    return -1;

}

int Max(Pro *page, int n)

{

    int e=page[0].time, i=0;

    while(i<n) //找出离现在时间最长的页面

    {

           if(e < page[i].time)

                  e=page[i].time;

           i++;

    }

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

           if(e==page[i].time)

           return i;

    return -1;

}

int Compfu(Pro *page, int i, int t, Pro p[])

{

    int count=0;

    for(int j=i; j<M; j++)

    {

           if(page[t].num==p[j].num ) break;

           else count++;

    }

    return count;    

}

int main()

{   

    int nu;

    cout<<"可用内存页面数:"<<endl;

    cin>>nu;

    if(nu>N)

    {

           cout<<"页面过大"<<endl;

           return 0;

    }

    Pro p[M];

    Pro page[N];

    char c;

    int m=0/*实际页数*/, t=0/*页面循环*/;

    float n=0; //缺页次数

    m = Input(m, p);      

   

    do{       

           for(int i=0; i<nu; i++)//初始化页面基本情况

           {

                  page[i].num=0;

                  page[i].time=2-i;

           }

           /*int j=0,count=1;

           page[0].num=p[0].num;

           int i=1,k=1;

           while(i<N)

           {

           int flag=1;

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

           if(p[k].num==page[i].num)

           {n++;flag=0;break;}

           if(flag==1){page[i].num=p[k].num;i++;}

           count++;k++;

    }*/

        i=0;         

        cout<<"f:FIFO页面置换"<<endl;

           cout<<"l:LRU页面置换"<<endl;

           cout<<"o:OPT页面置换"<<endl;

           cout<<"按其它键结束"<<endl;

           cin>>c;

          

           if(c=='f')//FIFO页面置换

           {

                  n=0;

                  cout<<"页面置换情况:   "<<endl;

                  while(i<m)

                  {

                         if(Search(p[i].num, page, nu)>=0) i++;//找到相同的页面

                         else

                         { 

                                if(t==nu) t=0;

                                n++;//缺页次数加1

                                page[t].num=p[i].num;

                                Print(page, nu);

                                t++;

                                i++;

                         }

                  }

                  cout<<"缺页次数:"<<n<<"    缺页率:"<<n/m<<endl;        

           }

           i=0;

           if(c=='l')//LRU页面置换

           {

                  n=0;

                  cout<<"页面置换情况: "<<endl;

                  while(i<m)

                  {

                         if(Search(p[i].num, page, nu)>=0)

                         {

                                int j=Search(p[i].num, page, nu);

                                for(int k=j; k>0; k--)

                                       page[k].num=page[k-1].num;

                                page[k].num=page[j].num;

                                i++;

                         }

                         else

                         {

                                if(t==nu) t=0;

                                n++;

                                for(int k=nu-1; k>0; k--)

                                       page[k].num=page[k-1].num;

                                page[k].num=p[i].num;

                                Print(page, nu);

                                t++;

                                i++;

                         }

                  }

               cout<<"缺页次数"<<n<<"    缺页率"<<n/m<<endl;

           }

           if(c=='o')//OPT页面置换

           {

                  n=0;

                  while(i<m)

                  {

                         if(Search(p[i].num, page, nu)>=0) i++;

                         else

                         {

                                int temp=0, cn;

                                for(t=0; t<nu; t++)

                                {

                                       if(temp < Compfu(page, i, t, p))

                                       {

                                              temp=Compfu(page,i,t,p);

                                              cn=t;

                                       }

                                }

                                page[cn]=p[i];

                                n++;

                                Print(page, nu);

                                i++;

                         }

                  }

                  cout<<"缺页次数"<<n<<"    缺页率"<<n/m<<endl;

           }            

    }while(c=='f'||c=='l'||c=='o');  

    return 0;

}

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

《计算机操作系统》实验报告班级:姓名:学号:实验一进程控制与描述一、实验目的通过对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...

操作系统实验报告

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

操作系统实验报告

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

操作系统原理实验报告(最终版)

键入文字课程名称学院专业班姓名学号指导教师XX学校实验报告20xx年3月目录实验1进程管理3一实验目的3二实验内容3三实验要求3四程序说明和程序流程图4五程序代码5六程序运行结果及分析7七指导教师评议8实验2进...

操作系统实验报告

实验二进程管理二进程的控制实验思考题1可执行文件加载时进行了哪些处理解可执行文件加载时首先是创建一个新进程的fork系统调用然后用于实现进程自我终止的exit系统调用改变进程原有代码的exec系统调用用于将调用...

操作系统 实验报告 文件管理

昆明理工大学信息工程与自动化学院学生实验报告201201学年第二学期课程名称操作系统开课实验室年月日一实验目的用C或C语言编写和调试一个简单的文件系统模拟文件管理的基本功能从而对各种文件操作命令的实质内容和执行...

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