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

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

一、目的

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

  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;elsereturn false;
}//(2)将PCB插入就绪队列中
void EnterQueue(Linkqueue &L, int x)
{T s = (T)malloc(sizeof(T)); //创建一个新结点ss->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; //往后移动}//找到了idif (pcb[p->next->data].id == id){//归还内存ram_size = ram_size + pcb[p->next->data].size;numpcb--;                //总的进程数-1p->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进程的完成时间,加深了对先来先服务进程的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/288365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql日志:undo log、redo log 、bin log、两阶段提交

借鉴&#xff1a; https://blog.csdn.net/Huangjiazhen711/article/details/127900821 https://blog.csdn.net/qq_42757463/article/details/132618759 https://blog.csdn.net/weixin_62458944/article/details/132721814 https://blog.csdn.net/m0_73311735/article/details/1…

如何通过ETLCloud的API对接功能实现各种SaaS平台数据对接

前言 当前使用SaaS系统的企业越来越多&#xff0c;当我们需要对SaaS系统中产生的数据进行分析和对接时就需要与SaaS系统提供的API进行对接&#xff0c;因为SaaS一般是不会提供数据库表给企业&#xff0c;这时就应该使用ETL&#xff08;Extract, Transform, Load&#xff09;的…

Potplayer播放器远程访问群晖WebDav本地资源【内网穿透】

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是&#xff1a;1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透&#xff0c;映射至公网4 使用固定地址在potplayer访问webdav 国内流媒体平台的内容…

线上盲盒小程序的优势

目前&#xff0c;我国盲盒市场规模即将达到300亿元&#xff0c;盲盒已经进入了发展的爆发期。 盲盒 随着人们的生活水平不断提高&#xff0c;对消费市场要求也越来越高。面对大家不断升级的消费体验&#xff0c;盲盒也是抓住了消费者的好奇心和惊喜感&#xff0c;消费者在购买…

如何下载知网论文、专利的PDF格式

知网的论文格式有其特有的格式&#xff1a;CAJ。将CAJ格式转化为Word或者PDF非常麻烦&#xff0c;且会出现乱码的情况&#xff0c;直接用知网官方的CAJ浏览器也不太方便。为此&#xff0c;困扰了许久。 其实&#xff0c;知网可以直接下载PDF格式&#xff0c;只需在浏览器上安装…

layui 树组件tree 通过API获取数据

一、简单 var treedata[];tree.render({elem: #addLeftType,id: demoId,data: treedata,showCheckbox: true,oncheck: function(obj){console.log(obj.data); // 得到当前点击的节点数据console.log(obj.checked); // 节点是否被选中console.log(obj.elem); // 得到当前节点元素…

真VS假(数字化前提)

元宇宙最近消停了很多&#xff0c;起始这个词刚出来的时候&#xff0c;很多人搞不清楚&#xff0c;元宇宙就是看待真假一个典范。如果对真假有个清晰的认知&#xff0c;那么对于看待很多事情&#xff0c;会给您带来不一样的视角&#xff0c;不仅仅是对企业数字化&#xff0c;可…

【DOM笔记四】事件高级!(注册/删除事件、DOM事件流、事件对象、事件委托、鼠标 / 键盘事件、相关案例)

文章目录 7 事件高级7.1 注册事件概述7.2 删除事件7.3 DOM事件流7.4 事件对象7.5 事件委托7.6 鼠标事件7.6.1 常用的鼠标事件7.6.2 鼠标事件对象 7.7 键盘事件7.7.1 常用的键盘事件7.7.2 键盘事件对象 7 事件高级 7.1 注册事件概述 给元素添加事件&#xff0c;称为注册事件或…

从零开始构建高效的网校平台:在线教育系统源码的开发指南

随着科技的不断发展&#xff0c;在线教育在现代社会中变得愈发重要。本文将为您提供一份详尽的指南&#xff0c;从零开始构建高效的网校平台&#xff0c;覆盖在线教育系统源码的关键开发步骤。 第一步&#xff1a;明确需求和目标 在开始之前&#xff0c;明确您的网校平台的需…

基于深度学习的动物检测识别系统(含UI界面、yolov5、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov5 yolov5主要包含以下几种创新&#xff1a;         1. 添加注意力机制&#xff08;SE、CBAM等&#xff09;         2. 修改可变形卷积&#xff08;DySnake-主干c…

青少年CTF-qsnctf-Web-Queen

题目环境&#xff1a; 题目难度&#xff1a;★★ 题目描述&#xff1a;Q的系统会不会有漏洞&#xff1f; 看到了登录窗口&#xff0c;使用burp suite工具进行抓包 burp suite抓包 admin 1 Repeater重放Send放包 Your IP is not the administrator’s IP address! 您的IP不是管理…

管理类联考——数学——真题篇——按题型分类——充分性判断题——蒙猜A/B

老规矩&#xff0c;看目录&#xff0c;平均3-5题 文章目录 A/B2023真题&#xff08;2023-19&#xff09;-A-选项特点&#xff1a;两个等号&#xff1b;-判断需联立的难易&#xff1a;难&#xff0c;看着感觉需要联立&#xff0c;所以判断联立需要有理论支撑&#xff0c;不然还…