【快速解决】实验一:模拟实现进程的创建《操作系统上机》实验报告

目录

实验要求

正文开始 

​编辑 难点讲解

 结语 


实验要求

实验一:进程的创建

一、实验项目类型:设计型

二、实验目的和要求

加深对进程概念的理解,熟悉PCB的组织,深入了解创建进程的一般过程掌握用队列组织进程的方法。

三、实验内容

编程实现创建原语,形成就绪队列,模拟实现进程的创建过程。

具体内容包括:

1、确定进程控制块的内容,用链表组织进程控制块;

2、完成进程创建原语;

四、实验主要仪器设备

个人计算机、C程序编译器

五、实验具体内容和步骤的说明

这个实验主要考虑二个问题:如何组织进程、如何创建进程。

1、进程的组织:

首先就要设定进程控制块的内容。进程控制块PCB记录各个进程执行时的所有信息,不同的操作系统,进程控制块所记录的信息内容不一样。操作系统功能越强,软件也越庞大,进程控制块所记录的内容也就越多。本次实验只使用必不可少的信息。一般操作系统中,无论进程控制块中信息量多少,信息都可以大致分为以下四类: 

① 标识信息

每个进程都要有一个惟一的标识符,用来标识进程的存在和区别于其他进程。这个标识符是必不可少的,可以用符号或编号实现,它必须是操作系统分配的。本实验中要求,采用编号方式,也就是为每个进程依次分配一个不相同的正整数。

② 说明信息

用于记录进程的基本情况,例如进程的状态、等待原因、进程程序存放位置、进程数据存放位置等等。本模拟实验中,因为进程没有数据和程序,仅使用进程控制块模拟进程,所以这部分内容仅包括进程状态

③ 现场信息

现场信息记录各个寄存器的内容。当进程由于某种原因让出处理器时,需要将现场信息记录在进程控制块中,当进行进程调度时,从选中进程的进程控制块中读取现场信息进行现场恢复。现场信息就是处理器的相关寄存器内容,包括通用寄存器、程序计数器和程序状态字寄存器等。在实验中,可选取几个寄存器作为代表。用大写的全局变量AX、BX、CX、DX模拟通用寄存器、大写的全局变量PC模拟程序计数器、大写的全局变量PSW模拟程序状态字寄存器。本实验要求读取一个寄存器的值,予以输出

④ 管理信息

管理信息记录进程管理和调度的信息。例如进程优先数、进程队列指针等。实验中,仅包括队列指针。

综合上面内容,建议进程控制块结构定义如下:

struct  pcb  

{int  name;  //进程标识符

int  status;  //进程状态

int  ax,  bx,  cx,  dx;  //进程现场信息,通用寄存器内容

int  pc;                //进程现场信息,程序计数器内容

int  psw;              //进程现场信息,程序状态字寄存器内容

int  next;              //下一个进程控制块的位置

}

    

进程控制块定义好后,考虑如何组织进程控制块。多道程序设计系统中,往往同时创建多个进程。在单处理器的情况下,每次只能有一个进程处于运行态,其他的进程处于就绪状态或阻塞状态。为了便于管理,通常把处于相同状态的进程的进程控制块链接在一起。

单处理器系统中,正在运行的进程只有一个。因此,单处理器系统中的进程控制块分成三个队列

①、一个正在运行进程的进程控制块;

②、就绪进程的进程控制块组成的就绪队列;

③、阻塞进程的进程控制块组成的阻塞队列。

由于实验模拟的是进程调度,没有对阻塞队列的操作,所以实验中只有一个指向正在运行进程的进程控制块指针一个就绪进程的进程控制块队列指针。操作系统的实现中,系统往往在主存中划分出一个连续的专门区域存放系统的进程控制块,实验中应该用数组模拟这个专门的进程控制块区域,定义如下:

#define   n   10                //假定系统允许进程个数为10

struct   pcb   pcbarea[n];        //模拟进程控制块区域的数组

这样,进程控制块的链表实际上是数据结构中使用的静态链表。进程控制块的链接方式可以采用单向和双向链表,实验中,进程控制块队列采用单向静态链表。为了管理空闲进程控制块,还应该将空闲控制块链接成一个队列。

实验中将采用时间片轮转调度算法,这种算法是将进程控制块按照进入就绪队列的先后次序排成队列。对就绪队列的操作就是从队头摘下一个进程控制块和从队尾挂入一个进程控制块。因此为就绪队列定义两个指针,一个头指针,指向就绪队列的第一个进程控制块;一个尾指针,指向就绪队列的最后一个进程控制块。

实验中指向运行进程的进程控制块指针、就绪队列指针和空闲进程控制块队列指针定义如下:

int  run;   //定义指向正在运行进程的进程控制块的指针

struct

{int   head;

int   tail;

}ready;   //定义指向就绪队列的头指针head和尾指针tail

int   pfree;   //定义指向空闲进程控制块队列的指针

2、进程创建。

进程创建是一个原语,因此在实验中应该用一个函数实现,进程创建的过程应该包括:

①申请进程控制块:进程控制块的数量是有限的,如果没有空闲进程控制块,则进程不能创建,如果申请成功才可以执行第②步;

②申请资源:除了进程控制块外,还需要有必要的资源才能创建进程,如果申请资源不成功,则不能创建进程,并且归还已申请的进程控制块;如果申请成功,则执行第三步,实验无法申请资源,所以模拟程序忽略了申请资源这一步;

③填写进程控制块:将该进程信息写入进程控制块内,实验中只有进程标识符、进程状态可以填写,每个进程现场信息中的寄存器内容由于没有具体数据而使用进程(模拟进程创建时,需输入进程标识符字,进程标识符本应系统建立,并且是惟一的,输入时注意不要冲突),刚刚创建的进程应该为就绪态,然后转去执行第四步;

④挂入就绪队列:如果原来就绪队列不为空,则将该进程控制块挂入就绪队列尾部,并修改就绪队列尾部指针;如果原来就绪队列为空,则将就绪队列的头指针、尾指针均指向该进程控制块,进程创建完成。

3、主程序:

完成上述功能后,编写主函数进行测试:首先建立一个就绪队列,手工输入信息建立几个进程;然后输出每个进程的进程id,察看结果。

注意:

这篇文章中小光会带你们将老师布置的实验内容这部分,详细的讲解一下,大家可以直接复制代码,也可以学习一下怎么写,在这个基础上加以拓展,这样就不会查重了。 

正文开始 

让我们先来看一下实验要求中的代码(代码如下

#include <stdio.h>
#include <stdlib.h>
#define READY 1
#define MAX_PCB 10 struct PCB {int pid;  int state;int ax;int bx;int cx;int dx;int pc;int psw;struct PCB* next;
};struct PCB pcbPool[MAX_PCB];
int allocPCBCount = 0;  struct PCB* readyQueueHead;
struct PCB* readyQueueTail;void createProcess() {struct PCB* pcb;if(allocPCBCount >= MAX_PCB) {printf("No free PCB\n");return;} else {pcb = &pcbPool[allocPCBCount++]; allocPCBCount++;}printf("Enter pid: ");scanf("%d", &pcb->pid);pcb->state = READY; // 初始化寄存器值pcb->ax = 0; //将该PCB的ax寄存器值设置为0pcb->bx = 0;pcb->cx = 0;pcb->dx = 0;pcb->pc = 0;pcb->psw = 0;if(readyQueueHead == NULL) {readyQueueHead = readyQueueTail = pcb; } else {readyQueueTail->next = pcb;readyQueueTail = pcb;}
}int main() {readyQueueHead = readyQueueTail = NULL;createProcess();createProcess();struct PCB* p;for(p = readyQueueHead; p != NULL; p = p->next) {printf("pid: %d state: %d ax: %d bx: %d cx: %d dx: %d pc: %d psw: %d\n",p->pid, p->state, p->ax, p->bx, p->cx, p->dx, p->pc, p->psw);}return 0;
}

 对以上代码进行一下解释防止有人看不到创建过程:

  1. 首先定义了进程状态和最大进程数的宏,以及进程控制块(PCB)的数据结构,其中包含了进程的所有必要信息。

  2. 然后使用一个PCB池来预先分配PCB的内存,并定义两个指针readyQueueHead和readyQueueTail来维护就绪队列。

  3. createProcess函数实现了进程的创建和PCB的初始化: (1) 首先检查PCB池是否还有可用PCB,如果满了则返回错误 (2) 然后从池中分配一个PCB,并填写进程信息如PID (3) 初始化PCB中的寄存器状态值为0 (4) 最后将PCB插入到就绪队列的尾部

  4. main函数先做就绪队列的初始化,然后调用createProcess来创建两个进程。

  5. 通过遍历就绪队列并打印每个PCB的信息,可以验证进程创建和队列管理的正确性。

  6. 这样通过PCB池、就绪队列和创建函数的配合,实现了进程控制块的动态分配与回收,以及进程状态的维护和管理。

展示一下运行效果图(如果大家的运行效果是这样就说明完成了)

我使用是编译环境是DevC++大家也可以使用其他的编译环境。

 难点讲解

pcb->state = READY;这个是什么意思

pcb->state = READY;这行代码的作用是设置PCB的状态为就绪(READY)状态。

这里我使用了一个宏定义:

#define READY 1

将就绪状态定义为1。

所以pcb->state = READY; 就会将pcb的state字段设置为1,表示该PCB对应的进程现在是就绪(ready)状态。

之所以要设置状态,是为了后续在调度算法选择新进程运行时,可以根据进程状态来判断,只有就绪状态的进程才能被调度运行。

此外还可以定义其它状态,如:

#define RUNNING 2 
#define BLOCKED 3

设置状态主要是为了在程序中表示和跟踪一个进程的当前情况。

createProcess();   createProcess();这个为什么要写两个 

createProcess(); 函数是用来创建一个新的进程并将其添加到就绪队列中的。

之所以示例代码中调用了两个 createProcess();,主要是为了创建两个进程做测试:

createProcess();  // 创建第一个进程
createProcess();  // 创建第二个进程

创建第一个进程后,就绪队列中只有一个进程。

再创建第二个进程后,就绪队列中就已经有两个进程了。

这样当我们后面遍历就绪队列并打印每个进程的信息时,可以看到两个进程的输出,验证创建和就绪队列管理是否正确。

如果只调用了一次 createProcess();,那么就绪队列中只会有一个进程,输出也就只有一个进程的信息,不太容易观察到链表和过程是否正确。

所以调用两次主要是为了创建多个进程,方便后续的打印调试与验证。

PCB的组成部分和需要体现的信息。 

struct PCB {int pid; // 进程标识符int state; // 进程状态 int ax; // 通用寄存器int bx;int cx;int dx;int pc; // 程序计数器int psw; // 程序状态字struct PCB* next; // 指向下一个PCB的指针  
};

以上PCB主要修改了以下部分:

  1. 添加了ax、bx、cx、dx通用寄存器
  2. 添加了pc程序计数器
  3. 添加了psw程序状态字寄存器

这样PCB中就包含了所需的标识信息、说明信息、现场信息和管理信息。

后续在创建进程时,可以要求输入或随机生成这些寄存器的值;在调度运行过程中,需要保存和恢复这些寄存器的现场。

 初始化寄存器值   pcb->ax = 0;   pcb->bx = 0;   pcb->cx = 0;   pcb->dx = 0;   pcb->pc = 0;   pcb->psw = 0;是什么意思

 这几行代码是用于初始化新创建的PCB中的寄存器的值,将它们都设置为0。

具体来说:

pcb->ax = 0; 意思是将该PCB的ax寄存器值设置为0。

pcb->bx = 0; 意思是将该PCB的bx寄存器值设置为0。

以此类推,将cx、dx、pc和psw寄存器都设置为了0。

之所以要这么做初始化,主要有以下两个原因:

  1. 刚创建的新进程,它的寄存器内容应该是未定义的。在实际中,可能是随机数或其它值,但比较简单的方法是初始化为0。

  2. 为了后面打印输出时,这些寄存器有一个确定的值,便于显示,验证PCB结构和数据是否正确。

如果不进行初始化,打印输出时就是一些未定义的随机值,不方便调试。

所以这些代码就是设置新PCB的寄存器值为0,主要是为了简化处理和打印输出。

if(allocPCBCount >= MAX_PCB)这个什么意思 

这个if语句是用于检查当前PCB池中是否还有可用的PCB来分配给新进程。

具体逻辑是:

  1. 定义了最大PCB数量MAX_PCB,例如10

  2. allocPCBCount记录当前已经分配出去的PCB数量

  3. 当去申请新PCB时,先检查:

    if(allocPCBCount >= MAX_PCB)

    如果已分配数量大于等于最大数量,表示PCB池已满,没有可分配的PCB

  4. 这个时候就会打印输出 "No free PCB" 来标示分配失败

  5. 并且return直接退出,不再执行后续PCB分配逻辑

所以这个if语句就是控制整个PCB申请过程的关键逻辑,用来检查和处理PCB池为空时的情况。

在主函数中,可以多次调用createProcess来模拟申请PCB,当分配到最大数后,再调用就会失败,这就完成了PCB申请和管理的基本机制。

这样就结束了,感谢大家的观看,百分百成功,不会出现运行不了的问题。但一定要按照小光的代码复制,全部复制粘贴就行了。

 结语 

关注小光,小光帮你写实验报告(不是真的帮你写,就是我写好,你直接复制拿走的那种)也可以看看小光的其他文章。

🌌点击下方个人名片,交流会更方便哦~(欢迎到博主主页加入我们的 CodeCrafters联盟一起交流学习↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓    

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

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

相关文章

数据库系统之常用数据库你用过几个?

MySQL 开发厂商&#xff1a;AB公司——>Sun公司——>甲骨文公司 最新版本&#xff1a;5.7.43、8.0.34 发行方式: 社区版&#xff08;MySQL Community Server&#xff09; 免费&#xff0c;MySQL不提供任何技术支持 商业版&#xff08;MySQL Enterprise Edition&#xff0…

加班做报表被嘲低效!快用大数据分析工具

做数据分析报表很耗时间&#xff0c;因为不仅要解决多业务系统数据质量标准不一问题&#xff0c;还需要进行大量的公式计算、报表设计与制作。但那是以前&#xff0c;在大数据分析工具强势崛起的当下&#xff0c;这些工作都能交给大数据分析工具来做了。以前是花90%的时间做报表…

9.Docker的虚悬镜像-Dangling Image

1.虚悬镜像的概念 虚悬镜像 (Dangling Image) 指的是仓库名 (镜像名) 和标签 TAG 都是 的镜像。 2.构建本地虚悬镜像 这里我以unbuntu为例来说明。 2.1 编写Dockerfile文件 FROM ubuntu:22.042.2 根据Dockerfile文件构建虚悬镜像 docker build .上面这段命令&#xff0c…

选择ERP系统的关键指标

在制造业工厂中&#xff0c;选择一个合适的ERP系统能够显著提升生产效率、优化资源管理、增强决策支持。然而&#xff0c;如何从众多ERP系统中选择一个适合自己企业的系统&#xff0c;是许多负责人在面临的问题。本文将详细介绍选择ERP系统的关键指标&#xff0c;帮助制造业工厂…

python查看目录属性

os.chown(path, uid, gid)

[MySQL-基础]SQL语句

目录 hello! 这里是欧_aita的频道。 今日语录: 只有放弃才是真正的失败。 祝福语&#xff1a;愿你的代码生活充满注释&#xff0c;逻辑清晰&#xff0c;debug之路畅通无阻。 大家可以在评论区畅所欲言&#xff0c;可以指出我的错误&#xff0c;在交流中共同进步。 欢迎关注我的…

基于51单片机的病床呼叫系统设计

**单片机设计介绍&#xff0c; 基于51单片机的病床呼叫系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的病床呼叫系统是一种用于医疗机构的设备&#xff0c;旨在提供快速、可靠的病人呼叫和监控功能。以下是…

Centos7使用rpm安装mysql 5.7.43

Centos7使用rpm安装mysql 5.7.43 1、下载rpm包 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.43-1.el7.x86_64.rpm-bundle.tar2、解压并安装 tar xf mysql-5.7.43-1.el7.x86_64.rpm-bundle.tar yum -y install mysql-*3、按需修改mysql配置 #注意&a…

Django框架环境的搭建(图文详解)

目录 day01 Web框架和Django基础 1.web框架底层 1.1 网络通信​编辑 1.2 常见软件架构 1.3 手撸web框架 2.web框架 2.1 wsgiref 2.2 werkzeug 2.3 各框架的区别 3.快速上手django框架 3.1 安装 3.2 命令行 3.3 Pycharm 4.虚拟环境 4.1 创建虚拟环境 - 命令行 4…

页面添加水印效果实现

页面效果&#xff1a; 源代码&#xff1a; <div id"water-wrapper"></div> <div><div>111111111111111111111111111111111111111111111111111111111111111111111111111111111111</div><div>1111111111111111111111111111111111…

电线电缆行业生产管理怎么数字化?

行业介绍 随着市场环境的变化和现代生产管理理念的不断更新&#xff0c;电缆的生产模式也在发生转变&#xff0c;批量小&#xff0c;规格多&#xff0c;交期短的新型制造需求逐年上升&#xff0c;所以企业车间管理的重要性越发凸显&#xff0c;作为企业良性运营的关键&#xf…

2023 年 亚太赛 APMCM (A题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 完整内容可以在文章末尾领取&#xff01; 问题1 图像处理&am…

硬核神作|2w字带你拿下Sentinal

目录 Sentinel概述 基本介绍 Sentinel 基本核心概念 Sentinel安装 简单安装启动 启动配置项 SpringCloud简单整合 实战架构 父工程pom文件 teacher-service服务 student-service服务 测试 整合Sentinel SpringCloud微服务保护方案解读 服务雪崩定义 问题的产生 …

AIGC重塑教育:AI大模型驱动的教育变革与实践

这次&#xff0c;狼真的来了。 AI正迅猛地改变着我们的生活。 根据高盛发布的一份报告&#xff0c;AI有可能取代3亿个全职工作岗位&#xff0c;影响全球18%的工作岗位。在欧美&#xff0c;或许四分之一的工作可以用AI完成。另一份Statista的报告预测&#xff0c;仅2023年&#…

【Linux】make/Makefile 进度条小程序

目录 一&#xff0c;认识 make/makefile 二&#xff0c;实例代码 1&#xff0c;依赖关系 2&#xff0c;原理 3&#xff0c;项目清理 4&#xff0c;测试讲解 三&#xff0c;Linux第一个小程序&#xff0d;进度条 game.h game.c test.c 程序详解 一&#xff0c;认识 m…

教你如何将Web项目部署到Linux中

文章目录 前言0. 什么是部署1. 调整代码达成一致2. 数据库建表3. 构建项目并打包4. 拷贝到 Tomcat 中5. 效果总结 前言 在我们完成了一个Web项目后, 我们该怎样将项目部署到 Linux 系统中呢? 本文就来简单讲解一下. 文章已部署本人的博客系统代码展开讲解. 关注收藏, 开始学…

NeurIPS 2023 | RGIB:对抗双边图噪声的鲁棒图学习

▐ 摘要 链接预测[1,2]是图学习的一种基础任务&#xff0c;用于判断图中的两个节点是否可能相连&#xff0c;被广泛应用于药物发现、知识图谱补全和在线问答等实际场景。尽管图神经网络&#xff08;Graph Neural Network&#xff0c;GNN&#xff09;在该问题的性能上取得了显著…

机器学习的概念和类型

1、人工智能、机器学习、深度学习之间的关系 人工智能&#xff08;AI&#xff09;是广泛的概念&#xff0c;指赋予计算机智能特性。机器学习&#xff08;ML&#xff09;是AI的一个分支&#xff0c;是指通过计算机学习和改进性能。深度学习&#xff08;DL&#xff09;是ML的一类…

搭个网页应用,让ChatGPT帮我写SQL

大家好&#xff0c;我是凌览。 开门见山&#xff0c;我搭了一个网页应用名字叫sql-translate。访问链接挂在我的个人博客(https://linglan01.cn/about)导航栏&#xff0c;也可以访问https://www.linglan01.cn/c/sql-translate/直达sql-translate。 它的主要功能有&#xff1a;…

第95步 深度学习图像目标检测:Faster R-CNN建模

基于WIN10的64位系统演示 一、写在前面 本期开始&#xff0c;我们学习深度学习图像目标检测系列。 深度学习图像目标检测是计算机视觉领域的一个重要子领域&#xff0c;它的核心目标是利用深度学习模型来识别并定位图像中的特定目标。这些目标可以是物体、人、动物或其他可识…