操作系统实验报告一 进程调度

实验一 进程调度

任务一

一、实验名称

       进程调度-代码阅读并调试实验

二、实验目的

1、阅读下面源代码,完善程序中填空处内容。
2、阅读代码,写出调度算法、算法流程图和程序功能。
3、解释数据结构PCB的定义和作用。
4、为main()写出每行的注释。
5、调试并运行代码,写出结果。
进程调度源程序如下:

jingchendiaodu.cpp 
#include "stdio.h" 
#include <stdlib.h> 
#include <conio.h> 
#define getpch(type) (type*)malloc(sizeof(type)) 
#define NULL 0 
struct pcb { /* 定义进程控制块PCB */ 
char name[10]; 
char state; 
int super; 
int ntime; 
int rtime; 
struct pcb* link; 
}*ready=NULL,*p; 
typedef struct pcb PCB;   
  
sort() /* 建立对进程进行优先级排列函数*/ 
{ 
PCB *first, *second; 
int insert=0; 
if((ready==NULL)||((p->super)>(ready->super))) /*1 就绪队列为空或p的优先级大于就绪队列中第一个的优先级 */ 
{ 
p->link=ready; 
ready=p; 
} 
else /* 进程比较优先级,插入适当的位置中*/ 
{ 
first=ready; 
second=first->link; 
while(second!=NULL) 
{ 
if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/ 
{ /*插入到当前进程前面*/ 
p->link=second; 
first->link=p; 
second=NULL; 
insert=1; 
} 

else /* 插入进程优先数最低,则插入到队尾*/ 
{ 
2 first=first->link ; 
second=second->link; 
} 
} 
if(insert==0) first->link=p; 
} 
} 
 
input() /* 建立进程控制块函数*/ 
{ 
int i,num; 
clrscr(); /*清屏*/ 
printf("\n 请输入进程号?"); 
scanf("%d",&num); 
for(i=0;i<num;i++) 
{ 
printf("\n 进程号No.%d:\n",i); 
p=getpch(PCB); 
printf("\n 输入进程名:"); 
scanf("%s",p->name); 
printf("\n 输入进程优先数:"); 
scanf("%d",&p->super); 
printf("\n 输入进程运行时间:"); 
scanf("%d",&p->ntime); 
printf("\n"); 
p->rtime=0;p->state='w'; 
p->link=NULL; 
sort(); /* 调用sort函数*/ 
} 
} 
int space() 
{ 
int l=0; PCB* pr=ready; 
while(pr!=NULL) 
{ 
l++; 
pr=pr->link; 
} 
return(l); 
} 
disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/ 
{ 
printf("\n qname \t state \t super \t ndtime \t runtime \n"); 
printf("|%s\t",pr->name); 
printf("|%c\t",pr->state); 
printf("|%d\t",pr->super); 
printf("|%d\t",pr->ntime); 
printf("|%d\t",pr->rtime); 
printf("\n"); 
} 

check() /* 建立进程查看函数 */ 
{ 
PCB* pr; 
printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/ 
disp(p); 
pr=ready; 
printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/ 
while(pr!=NULL) 
{ 
disp(pr); 
pr=pr->link; 
} 
} 
destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ 
{ 
printf("\n 进程 [%s] 已完成.\n",p->name); 
free(p); 
} 
running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ 
{ 
(p->rtime)++; 
if(p->rtime==p->ntime) 
destroy(); /* 调用destroy函数*/ 
else 
{ 
(p->super)--; 
p->state='w'; 
sort(); /*调用sort函数*/ 
} 
} 
 main() /*主函数*/ 
{ 
int len,h=0; //定义两个int类型的变量
char ch; //定义一个字符型变量 
input(); //调用进程控制块函数,录入进程信息并排序
len=space(); //用len表示进程块数
while((len!=0)&&(ready!=NULL)) //当进程没有全部运行完时
{ 
ch=getchar(); //读取按任意键继续的“任意键”
h++; //执行次数加一
printf("\n The execute number:%d \n",h); //打印当前执行次数
p=ready; //p指向第一个就绪进程块
ready=p->link; //就绪指针指向p的下一个进程块
p->link=NULL; //将p的下一个进程块置为空
p->state='R'; //状态置为正在运行
check();//调用进程查看函数,打印进程调度信息 
running(); //运行进程p
printf("\n 按任一键继续......"); //提示用户按任意键继续
ch=getchar(); //存储“任意键”字符
} 
printf("\n\n 进程已经完成.\n"); //显示进程全部调度完成
ch=getchar();//存储“任意键”字符
}

三、实验过程

1、阅读下面源代码,完善程序中填空处内容。
已在上文作业调度源程序呈现
2、阅读代码,写出调度算法、算法流程图和程序功能。
(1)调度算法
采用动态优先级调度算法和先来先服务算法。 首先定义了进程控制块PCB,每一个进程控制块的信息有:进程名、状态、优先数、需要运行的时间和已经运行的时间,要求用户输入进程的名字、优先数和需要的运行时间。每个进程的状态是W(就绪)或R(运行)。
对于按进程优先数降序排好序的就绪队列,每一次优先级最高的进程获得CPU并运行一个时间片,结束后,runtime加1,如果runtime=ndtime,表示该进程已完成,则撤消该进程,否则优先数减1,然后把它插入就绪队列进行等待。
每进行一次进程调度都会打印一次当前正在运行的进程的信息和就绪队列中各个进程的信息。
每按一次任意键,就进行一次进程调度,直到所有进程都完成为止。
(2)算法流程图

在这里插入图片描述

(3)程序功能
模拟了动态优先级调度算法和先来先服务算法的过程,并利用进程控制块模拟作业加入就绪队列和进程撤销。

3、解释数据结构PCB的定义和作用。
(1)定义
PCB是为了便于系统描述和管理进程的运行,在OS的核心为每个进程专门定义的记录型数据结构,用来记录进程相关信息和管理进程运行。
(2)作用
PCB的作用是使一个在多道程序环境下不能独立运行的程序(含数据)成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。具体作用有:
(1)作为独立运行基本单位的标志,事实上,PCB已成为进程存在于系统中的唯一标志;
(2)能实现间断性运行方式;
(3)提供进程管理所需要的信息;
(4)提供进程调度所需要的信息;

                已在上文作业调度源程序呈现

6、调试并运行代码,写出结果。
输入进程信息如下:
在这里插入图片描述

进程调度结果如下:
在这里插入图片描述

四、实验总结

1、先来先服务算法(FCFS)按照进程变为就绪状态的先后次序分派CPU,比较有利于长作业,而不利于短作业(因为长作业能够长时间占据处理机);有利于CPU繁忙的作业,而不利于I/O繁忙的作业。

任务二

一、实验名称

     进程调度-代码阅读并调试实验

二、实验目的

1、编写并调试一个模拟的进程调度程序,采用“最高优先数优先”调度算法对五个进程进行调度。
  “最高优先数优先”调度算法的基本思想是把CPU分配给就绪队列中优先数最高的进程。
  静态优先数是在创建进程时确定的,并在整个进程运行期间不再改变。
动态优先数是指进程的优先数在创建进程时可以给定一个初始值,并且可以按一定原则修改优先数。例如:在进程获得一次CPU后就将其优先数减少1。或者,进程等待的时间超过某一时限时增加其优先数的值,等等。
2、编写并调试一个模拟的进程调度程序,采用“轮转法”调度算法对五个进程进行调度。
  轮转法可以是简单轮转法、可变时间片轮转法,或多队列轮转法。
  简单轮转法的基本思想是:所有就绪进程按FCFS排成一个队列,总是把处理机分配给队首的进程,各进程占用CPU的时间片相同。如果运行进程用完它的时间片后还未完成,就把它送回到就绪队列的末尾,把处理机重新分配给队首的进程。直至所有的进程运行完毕。

三、实验过程

1、“最高优先数优先”调度算法

首先定义了进程控制块PCB,每一个进程控制块的信息有:进程名、状态、优先数、需要运行的时间和已经运行的时间,要求用户输入5个进程的名字、优先数和需要的运行时间。每个进程的状态是W(就绪)或R(运行)。
对于按进程优先数降序排好序的就绪队列,每一次优先数最高的进程获得CPU并运行一个时间片,结束后,runtime加1,如果runtime=ndtime,表示该进程已完成,则撤消该进程,否则优先数减1,然后把它插入就绪队列进行等待。
每进行一次进程调度都会打印一次当前正在运行的进程的信息和就绪队列中各个进程的信息。
每按一次任意键,就进行一次进程调度,直到所有进程都完成为止
输入进程信息如下:
在这里插入图片描述

进程调度结果如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、“轮转法”调度算法

首先定义了进程控制块PCB,每一个进程控制块的信息有:进程名、状态、连接下一个进程的指针、需要时间片数和占用的时间片,要求用户输入5个进程的名字、优先数、占用的时间片数和需要的时间片。每个进程的状态是W(就绪)或R(运行)。
所有就绪进程按FCFS排成一个队列,总是把处理机分配给队首的进程,各进程占用CPU的时间片相同。如果运行进程用完它的时间片后还未完成,就把它送回到就绪队列的末尾,把处理机重新分配给队首的进程。直至所有的进程运行完毕。

输入进程信息如下:在这里插入图片描述

进程调度结果如下:
在这里插入图片描述

四、实验总结

1、“最高优先数优先”调度算法  
每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
  进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。

五、代码

1、“最高优先数优先”调度算法
#include "stdio.h"
#include <stdlib.h>
#include <conio.h>
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
#include<iostream>
using namespace std;
struct pcb   /* 定义进程控制块PCB */
{
    char name[10];
    char state;
    int super;
    int ntime;
    int rtime;
    struct pcb* link;
}*ready=NULL,*p;
typedef struct pcb PCB;

sort() /* 建立对进程进行优先级排列函数*/
{
    PCB *first, *second;
    int insert=0;
    if((ready==NULL)||((p->super)>(ready->super))) /*1就绪队列为空或p的优先级大于就绪队列中第一个的优先级*/
    {
        p->link=ready;
        ready=p;
    }
    else /* 进程比较优先级,插入适当的位置中*/
    {
        first=ready;
        second=first->link;
        while(second!=NULL)
        {
            if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/
            {
                /*插入到当前进程前面*/
                p->link=second;
                first->link=p;
                second=NULL;
                insert=1;
            }

            else /* 插入进程优先数最低,则插入到队尾*/
            {
                first=first->link;                  ;
                second=second->link;
            }
        }
        if(insert==0) first->link=p;
    }
}
input() /* 建立进程控制块函数 */
{
    int i;
    for(i=0; i<5; i++)
    {
        printf("\n 进程号No.%d:\n",i);
        p=getpch(PCB);
        printf("\n 输入进程名:");
        scanf("%s",p->name);
        printf("\n 输入进程优先数:");
        scanf("%d",&p->super);
        printf("\n 输入进程运行时间:");
        scanf("%d",&p->ntime);
        printf("\n");
        p->rtime=0;
        p->state='w';
        p->link=NULL;
        sort(); /* 调用sort函数*/
    }
}

int space()
{
    int l=0;
    PCB* pr=ready;
    while(pr!=NULL)
    {
        l++;
        pr=pr->link;
    }
    return(l);
}

disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/
{
    printf("\n qname \t state \t super \t ndtime \t runtime \n");
    printf("|%s\t",pr->name);
    printf("|%c\t",pr->state);
    printf("|%d\t",pr->super);
    printf("|%d\t",pr->ntime);
    printf("|%d\t",pr->rtime);
    printf("\n");
}

check() /* 建立进程查看函数 */
{
    PCB* pr;
    printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/
    disp(p);
    pr=ready;
    printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/
    while(pr!=NULL)
    {
        disp(pr);
        pr=pr->link;
    }
}

destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/
{
    printf("\n 进程 [%s] 已完成.\n",p->name);
    free(p);
}

running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/
{
    (p->rtime)++;
    if(p->rtime==p->ntime)
        destroy(); /* 调用destroy函数*/
    else
    {
        (p->super)--;
        p->state='w';
        sort(); /*调用sort函数*/
    }
}

main() /*主函数*/
{
    int len,h=0;
    char ch;
    input();
    len=space();

    while((len!=0)&&(ready!=NULL))
    {
        ch=getchar();
        h++;
        printf("\n The execute number:%d \n",h);
        p=ready;
        ready=p->link;
        p->link=NULL;
        p->state='R';
        check();
        running();
        printf("\n 按任一键继续......");
        ch=getchar();
    }
    printf("\n\n 进程已经完成.\n");
    ch=getchar();
}

2、“轮转法”调度算法
#include<stdio.h>
#include<malloc.h>
enum process_status{READY , RUN , FINISH}; 

typedef struct pcb
{
    char process_tag[20] ; 
    struct pcb *next ; 
    int time_slice ; // 轮转时间片
    int take_cpu_time ; //占用CPU时间片数
    int process_time ; //进程所需时间片数
    process_status status ; 
} PCB ;

typedef struct
{
    PCB *run ; //当前运行的进程指针
    PCB *ready ; //当前准备队列的头指针
    PCB *tail ; //准备队列的队尾指针
    PCB *finish ; //完成队列的指针
} PCBC ;
void init_pcbc(PCBC *p)
{
    p->run = NULL ;
    p->ready = NULL ;
    p->tail = NULL ;
    p->finish = NULL ;
}

void input_process(PCBC *pcbc)
{
   PCB *pcb ;
   pcb = (PCB*)malloc(sizeof(PCB)) ;
   printf("请输入进程标识符:") ;
   scanf("%s" , &pcb->process_tag) ;
   printf("输入格式为: (优先级,占用CPU时间片数,进程所需时间片数) : ") ;
   scanf("%d%d%d" , &pcb->time_slice , &pcb->take_cpu_time , &pcb->process_time) ;
   pcb->status = READY ; //初始化就绪状态
   //当就绪队列为空时
   if(pcbc->ready == NULL && pcbc->tail == NULL)
   {
       pcbc->ready = pcbc->tail = pcb ;
       pcb->next = NULL ;
   }
   else
   {
  
       pcb->next = pcbc->tail->next ;
       pcbc->tail->next = pcb ;
       pcbc->tail = pcb ;
   }
}

 void print_log(PCBC *pcbc)
 {
     PCB *ready , *finish ;
     ready = pcbc->ready ;
     finish = pcbc->finish ;
     printf("--------------------------------------------------  \n") ;
     printf("Run: \n") ;
     if(pcbc->run != NULL)
     {
        printf("%s  %04d  %04d  %04d \n" , pcbc->run->process_tag ,pcbc->run->time_slice , pcbc->run->take_cpu_time , pcbc->run->process_time) ;
     }
     else
     {
         printf("Run is empty! \n") ;
     }
     printf("Ready:\n") ;
     while(ready != NULL)
     {
         printf("%s  %04d  %04d  %04d \n" , ready->process_tag ,ready->time_slice , ready->take_cpu_time , ready->process_time) ;
         ready = ready->next ;
     }
     printf("Finish:\n") ;
     while(finish != NULL)
     {
         printf("%s  %04d  %04d  %04d \n" , finish->process_tag ,finish->time_slice , finish->take_cpu_time , finish->process_time) ;
         finish = finish->next ;
     }
 }

void run_pcbc_timeSlice(PCBC *xpcbc)
{
      PCBC *pcbc = xpcbc ;
      PCB *temp , *pre , *tail ;
     while(pcbc->ready != NULL)
     {
         pcbc->run = pcbc->ready ; 
         pcbc->ready = pcbc->ready->next ; //改变队首元素
         print_log(pcbc) ;
         pcbc->run->take_cpu_time += 1 ;
         pcbc->run->process_time -= 1 ;
         if(pcbc->run->process_time == 0)
         {
           if(pcbc->finish == NULL)
           {
               pcbc->finish = pcbc->run ;
               pcbc->finish->next = NULL ;
               tail = pcbc->finish ;
           }
           else
           {
              tail->next = pcbc->run ;
              tail = tail->next ;
              tail->next = NULL ;
           }
         }
         else
         {
            if(pcbc->run->time_slice == pcbc->run->take_cpu_time) //占用CPU时间片数到
            {
        
                pcbc->run->take_cpu_time = 0 ;
                pcbc->run->next = NULL ;
                pcbc->tail->next = pcbc->run ;
                pcbc->tail = pcbc->run ;
                if(pcbc->ready == NULL)
                {
                    pcbc->ready = pcbc->tail ;
                    pcbc->ready->next = NULL ;
                }
            }
            else
            {
                pcbc->run->next = pcbc->ready ;
                pcbc->ready = pcbc->run ;
            }
         }
     }
     pcbc->run = NULL ;
     print_log(pcbc) ;
}
int main()
{
    PCBC *pcbc ; //创建进程控制块链 ;
    pcbc = (PCBC*)malloc(sizeof(PCBC)) ;
    init_pcbc(pcbc) ; //初始化进程控制块链
    for(int i = 0 ; i < 5 ; i++)
    {
        input_process(pcbc) ; 
    }
    printf("------------------------\n") ;
    run_pcbc_timeSlice(pcbc) ;
    return 0 ;
}
  • 24
    点赞
  • 317
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年李富贵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值