实验一、进程创建、调度与撤消

实验一、进程创建、调度与撤消

一、目的

通过进程的创建和调度的设计来达到如下目的:

  1. 加深对进程概念的理解,明确进程和程序的区别;
  2. 进一步认识并发执行的概念,区别顺序执行和并发执行;
  3. 深入了解系统如何组织进程,创建进程;
  4. 进一步认识如何实现处理机调度。

二、内容

        在WINDOWS环境下模拟实验:

  1. 编写一程序,来模拟进程的创建和撤消,要求通过终端键盘输入几个作业的名称、大小、优先级等。系统为它创建进程,并把进程控制块PCB(进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、程序大小、已用CPU时间、进程状态等等)的内容送到终端显示器上输出。
  2. 同时模拟内存空间为作业分配内存空间,并把结果用图形形象地表示出来,同样通过终端输出。
  3. 从下面四个调度算法中,选择一个调度算法来实现进程调度:

        a、先来先服务调度算法;

        b、短进程优先调度算法;

        c、优先数调度算法;

        d、时间片轮法调度算法;

三、详细设计

该模拟系统主要,主要使用结构体存储PCB的基本信息和就绪队列链队LinkQueue,写了6个关键的函数,具体实现如下:

 ---PCB结构体、就绪队列LinkQueue(采用链队的存储方式)如下:

(1)//控制块PCB的信息
struct PCB
{
    char name[10];
    int id;
    int atime; //进程到达时间
    int stime; //服务时间,运行时间
    int ftime; //进程完成时间
    int size;
    int prior; //进程优先级
};

//使用链队进行存储

(2)//就绪队列
typedef struct Tnode *T; // struct Tnode的别名为*T
struct Tnode
{
    int data; //?什么数据/存储当前创建的进程数
    T next;   //指向就绪队列的下一位置
};

(3)//消息缓冲队列
struct Linkqueue
{
    T front, rear; //头指针和尾指针分别指向就绪队列的头部和尾部
};
 

 

---主要函数如下:

(1)InitQueue():初始化就绪队列,主要将指向就绪队列的头指针和尾指针初始化,方便后面进程的创建。

(2)EnterQueue() ——将PCB插入到链队L中。

(3)create_PCB()——创建进程,首先申请一个空的PCB,然后为该进程分配空间资源,然后初始化PCB,填入进程参数,最后通过调用EnterQueue()函数将该PCB插入到就绪链队L中。若内存不够则申请失败。

(4)sort_FCFS() ——采用先来先服务算法对就绪队列进行排序,遍历pcb,如果当前进程比后一个进程的到达时间长,就交换。

(5)Finish_Time()——计算经过sort_FCFS排序后的每个PCB进程的完成时间。

(6)kill_PCB( )——终止进程,将指定的就绪进程移出就绪队列中,并清除PCB中的信息。

(7)display_PCB() —— 显示已经在就绪队列中的进程。

四、源代码

详细源代码如下:

#include <stdio.h>
#include <stdlib.h>
// #define MAX_size 200 //表示最大内存
#define MAX_num 20 //单次最大进程数

//控制块PCB的信息
struct PCB
{
    char name[10];
    int id;
    int atime; //进程到达时间
    int stime; //服务时间,运行时间
    int ftime; //进程完成时间
    int size;
    int prior; //进程优先级
};

//使用链队进行存储

//就绪队列
typedef struct Tnode *T; // struct Tnode的别名为*T
struct Tnode
{
    int data; //?什么数据/存储当前创建的进程数
    T next;   //指向就绪队列的下一位置
};

//消息缓冲队列
struct Linkqueue
{
    T front, rear; //头指针和尾指针分别指向就绪队列的头部和尾部
};

//定义全局变量
Linkqueue L;      //消息缓冲队列结构体
PCB pcb[MAX_num]; //结构体PCB数组,MAX_num最大进程数
int numpcb = 0;   /当前已经创建的进程数目
int ram_size;     //内存大小

//就绪队列的初始化
void InitQueue()
{
    L.rear = L.front = (T)malloc(sizeof(T));
    if (!L.front)
        exit(-2);
    L.front->next = NULL;
}

//判断链队是否为空
bool EmptyQueue()
{
    if (L.front == L.rear)
        return true;
    else
        return false;
}

//(2)将PCB插入就绪队列中
void EnterQueue(Linkqueue &L, int x)
{
    T s = (T)malloc(sizeof(T)); //创建一个新结点s
    s->data = x;                //传入新结点s的数据域x值,此时x的值就是结构体数组的下标
    s->next = NULL;             //设置新结点s的指针域为空
    L.rear->next = s;           //将新结点s插入至当前链队末尾
    L.rear = s;                 //队尾指针指向新结点s
}

//(3)先来先服务,即 先到达,先服务 进行排序
void sort_FCFS(PCB *q, int num)
{
    for (int i = 0; i < num - 1; i++)
    {
        struct PCB temp;                  //临时变量,用于交换的中间量
        for (int j = i + 1; j < num; j++) //按先到达的排序
        {
            if (q[i].atime > q[j].atime)
            //如果前面的PCB比后面的更晚到达,就往后移
            {
                temp = q[i];
                q[i] = q[j];
                q[j] = temp;
            }
        }
    }
}

//(3)优先数调度算法排序(1为优先级最高)
void sort_Priority(PCB *q, int num)
{
    for (int i = 0; i < num - 1; i++)
    {
        struct PCB temp;                  //临时变量,用于交换的中间量
        for (int j = i + 1; j < num; j++) //按先到达的排序
        {
            if (q[i].prior > q[j].prior)
            //如果前面的PCB比后面的更晚到达,就往后移
            {
                temp = q[i];
                q[i] = q[j];
                q[j] = temp;
            }
            if (q[i].prior == q[j].prior)
            {
                if (q[i].atime > q[j].atime)
                {
                    temp = q[i];
                    q[i] = q[j];
                    q[j] = temp;
                }
            }
        }
    }
}

//(4)计算PCB的完成时间
void finish_Time(PCB *pcb, int numpcb)
{
    //先使用先来先服务进行排序
    // sort_FCFS(pcb, numpcb);
    //优先级调度算法
    sort_Priority(pcb, numpcb);

    for (int i = 0; i <= numpcb; i++)
    {
        //计算第一个进程的完成时间:达到时间+服务时间
        if (i == 0)

            pcb[0].ftime = pcb[0].atime + pcb[0].stime;
        else
        {
            if (pcb[i].atime > pcb[i - 1].ftime) //当前的到达时间比上一个的完成时间大的话,直接
                pcb[i].ftime = pcb[i].atime + pcb[i].stime;
            else
            {
                pcb[i].ftime = pcb[i - 1].ftime + pcb[i].stime;
                // printf("%d", pcb[i].ftime);
            }
        }
        // ram_size=ram_size+pcb[i].size;
    }
}

//(1)创建进程:申请PCB
void create_PCB()
{
    int num; //要创建的进程数目
    printf("\n--请输入要创建的进程数目:");
    scanf("%d", &num);

    while (num > MAX_num)
    {
        printf("*提示:进程数太大了,请重新输入!");
        scanf("%d", &num);
    };
    // 1、输入数据
    for (int i = 0; i < num; i++)
    {
        printf("*请输入进程id:");
        scanf("%d", &pcb[numpcb].id);
        printf("*请输入进程名:");
        scanf("%s", &pcb[numpcb].name);
        printf("请输入进程的优先级:");
        scanf("%d", &pcb[numpcb].prior);
        printf("*请输入进程到达时间:");
        scanf("%d", &pcb[numpcb].atime);
        printf("*请输入进程服务时间:");
        scanf("%d", &pcb[numpcb].stime);
        printf("*请输入进程大小:");
        scanf("%d", &pcb[numpcb].size);

        //判断一下内存还够不够
        if (pcb[numpcb].size > ram_size)
        {
            printf("*提示:内存不足,创建失败!\n");
            //结束创建
            break;
        }
        else
        {
            //将PCB插入到就绪队列中
            EnterQueue(L, numpcb);
            //提示用户
            printf("-----%d\n", pcb[numpcb].size);
            ram_size = ram_size - pcb[numpcb].size; //创建成功后,为该进程分配了空间,计算剩下的内存空间
            printf("剩下内存%d\n", ram_size);
            printf("*提示:恭喜%s进程创建成功!\n", pcb[numpcb].name);
            numpcb++; //创建成功后,进程数加一
            printf("_____________________________");
        }
        printf("\n");
    }
    printf("\n---共成功创建了%d个进程", numpcb);
    printf("\n---还剩下%d的内存空间!", ram_size);
}

//(6)终止进程,删除进程
void kill_PCB()
{
    int id;
    T p;
    p = L.front; //指向链队的第一个结点
    if (L.front == L.rear)
        printf("*提示:当前无进程!\n\n");
    else
    {
        printf("请输入要终止的进程id:");
        scanf("%d", &id);

        while (pcb[p->next->data].id != id)
        {
            if (p->next == NULL) //到最后没有找到改进程
                printf("*提示:进程不存在!\n\n");
            p = p->next; //往后移动
        }
        //找到了id
        if (pcb[p->next->data].id == id)
        {
            //归还内存
            ram_size = ram_size + pcb[p->next->data].size;
            numpcb--;                //总的进程数-1
            p->next = p->next->next; //删除该结点p->next
            /*当L.front->next==NULL时,说明当前杀死的进程是系统中最后一个进程,此时首位指针指向同一个位置*/
            if (L.front->next == NULL)
                L.front = L.rear;
            /*当p->next==NULL时,说明当前杀死的进程是队尾进程,此时尾指针指向p*/
            if (p->next == NULL)
                L.rear = p;
            while (p->next != NULL)
            {
                p->next->data--;
                pcb[p->next->data] = pcb[p->next->data + 1];
                p = p->next;
            }
        }

        printf("*提示:成功杀死进程!\n");
        printf("--当前内存剩余:%d!\n", ram_size);
        printf("--当前进程数为:%d\n", numpcb);
    }
}

void print(PCB *pcb, int numpcb)
{
    sort_FCFS(pcb, numpcb);
    for (int i = 0; i < numpcb; i++)
    {
        printf("-----第%d个:\n", i + 1);
        printf("进程ID:%d\n 进程名: %s\n 到达时间: %d\n 服务时间: %d\n 完成时间:%d\n", pcb[i].id, pcb[i].name, pcb[i].atime, pcb[i].stime, pcb[i].ftime);
    }
}

//(5)显示已经就绪的进程
void display_PCB()
{
    printf("\n当前numpcb:%d\n", numpcb);
    sort_FCFS(pcb, numpcb);
    // print(pcb, numpcb);
    // printf("计算时间\n");
    finish_Time(pcb, numpcb); //计算完成时间

    if (L.front == L.rear)
        printf("*提示:当前无进程!");
    else
    {
        T p;
        p = L.front->next;
        printf("-----就绪进程如下:------\n");
        printf("进程ID  进程名  优先级  到达时间 服务时间 完成时间 内存大小\n");
        while (p != NULL)
        {
            printf("%5d\t", pcb[p->data].id);
            printf("%4s\t", pcb[p->data].name);
            printf("%4d\t", pcb[p->data].prior);
            printf("%5d\t", pcb[p->data].atime);
            printf("%5d\t", pcb[p->data].stime);
            printf("%5d\t", pcb[p->data].ftime);
            printf("%5d\t", pcb[p->data].size);
            p = p->next;
            printf("\n");
        }
    }
}

//菜单
void menu()
{
    int n;
    while (1)
    {
        printf("\n*************进程演示系统*************\n");
        printf("             1.创建进程\n");
        printf("             2.查看进程\n");
        printf("             3.杀死进程\n");
        printf("             4.退出程序\n");
        printf("***************************************\n\n");
        printf("请输入你的选择(1-4):");

        scanf("%d", &n);
        switch (n)
        {
        case 1:
            create_PCB();
            break;
        case 2:
            display_PCB();
            break;
        case 3:
            kill_PCB();
            break;
        case 4:
            //退出
            break;
        default:
            printf("没有这个选项!");
            break;
        }
    }
}

int main()
{
    printf("\n请输入可用的内存大小:");
    scanf("%d", &ram_size);
    InitQueue(); //初始化就绪队列
    menu();
    return 0;
}

 

五、运行效果图

(1)界面初始图

 

(2)创建进程:

 

(3)显示已经在就绪队列中的进程(按照先来先服务进行排序输出):

 

(4)终止某进程

 

六、结果分析

        此次实验采用c语言模拟进程的创建与撤销,一方面,回忆和复习了原先学习过的链队的创建、插入、遍历等知识点,另一方面,通过写代码更加清楚的理解了PCB进程的创建的基本过程:(1)申请空白PCB;(2)为新进程分配资源;(3)初始化PCB;(4)将新进程插入到就绪队列中。

        本次实验还采用了先来先服务算法对PCB进程排序之后,再计算出每个PCB进程的完成时间,加深了对先来先服务进程的理解。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
进程调度课程设计 给需要的人 呵呵 实验进程调度实验 一、实验目的 通过对进程调度算法的模拟加深对进程概念和进程调度算法的理解。 二、实验要求 编写程序实现对5个进程调度模拟,要求至少采用两种不同的调度算法分别进行模拟调度。 备注: 1.可选择进程调度算法如下: 先来先服务调度算法 最短进程优先调度算法 简单时间片轮转调度算法 最高优先数优先调度算法(即把处理机分配给优先数最高的进程) 3. 最高优先数优先调度算法资料 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。    进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。  每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。  就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。  如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。    每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。   重复以上过程,直到所有进程都完成为止。、 流程图如下 :

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

m0_7Ella

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

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

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

打赏作者

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

抵扣说明:

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

余额充值