操作系统原理-模拟进程创建、终止、阻塞、唤醒原语——沐雨先生

一、实验题目: 模拟进程创建、终止、阻塞、唤醒原语

二、实验目的: 通过设计并调试创建、终止、阻塞、唤醒原语功能,有助于对操作系统中进程控制功能的理解,掌握操作系统模块的设计方法和工作原理。

三、实验环境:

1、硬件:PC机及其兼容机。

2、软件:Windows OS,MS—DOS OS,Turbo C 或 C++、VC++等。

四、实验内容:

1、设计创建、终止、阻塞、唤醒原语功能函数。

2、设计主函数,采用菜单结构(参见后面给出的流程图)。

3、设计“显示队列”函数,目的能将就绪、阻塞队列中的进程信息 显示在屏幕上,以供随时查看各队列中进程的变化情况。

五、算法流程图:

在这里插入图片描述

六、程序清单:

#include<stdio.h>
#include<string.h>
#include<windows.h>
int count=0;//记录进程数目typedef struct PCB{char pname[10];//进程名int ppri;//优先级 1-低,2-中,3-高int pruntime;//运行时间int pstatus;//运行状态 1-阻塞,2运行,3就绪struct PCB *next;//指针,指向下一个PCB
}PCB;void menu(){printf("---------OS实验一:模拟进程创建、阻塞、唤醒、终止原语---------\n");printf("----------------------------0.退出----------------------------\n");printf("----------------------------1.创建----------------------------\n");printf("----------------------------2.阻塞----------------------------\n");printf("----------------------------3.唤醒----------------------------\n");printf("----------------------------4.终止----------------------------\n");printf("----------------------------5.显示----------------------------\n");printf("---------------------请输入您需要的功能(0-5)------------------\n");printf("--------------------------------------------------------------\n");printf("各功能简要说明:\n");printf("创建:在本实验中,该功能仅实现建立 PCB,初始化 PCB,并将该 PCB放入就绪队列中。\n");printf("阻塞:在本实验中,实现的功能为,根据用户输入的进程名称查看该进程是否处在运行状态,若处在运行状态,修改该进程PCB的状态,并将该进程转入阻塞队列;若该进程处在其它状态,则给出相应的提示信息;若该进程不存在,也需要给出相应的提示信息。\n");printf("唤醒:功能类似阻塞功能,注意:若阻塞队列为空,则不能执行唤醒功能。\n");printf("终止:根据用户输入要结束的进程名称,从就绪队列、阻塞队列和正在运行的进程中找到相应的进程 PCB,并将该 PCB 从相应队列中删除。若该进程不存在,需要给出提示。\n");printf("显示:将就绪队列、阻塞队列中的进程列表和正在运行的进程显示出来。\n");
}void run(PCB *head2,PCB *head3){//从就绪队列中选队首进程运行,保证有一个进程处于运行状态PCB *p=head3->next;if(p){head2->next=p;p->pstatus=2;head3->next=p->next;free(p);}
}void insert(PCB *head3,PCB *temp){//将新创建的进程插入就绪队列PCB *p;p=head3;while(p->next!=NULL)//找尾结点p=p->next;p->next=temp;temp->next=NULL;
}int check(PCB *head,PCB *temp){//检查temp进程与已有进程是否重复PCB *p=head;while(p->next){p=p->next;if(strcmp(p->pname,temp->pname)==0)return 0;}return 1;
}void Delete(PCB *head,PCB *temp){/*head为链表头结点,temp为将要删除的结点*/PCB *p=head,*q=temp->next;while(p)//寻找temp的上一个节点if(p->next==temp){p->next=q;free(temp);return;}elsep=p->next;
}void create(PCB *head1,PCB *head2,PCB *head3){//创建进程int compare1,compare2,compare3;PCB *temp;//一个新节点temp=(PCB*)malloc(sizeof(PCB));system("cls");printf("---------------进程创建---------------\n");printf("请输入进程名:");scanf("%s,temp->pname");getchar();compare1=check(head1,temp);//检查进程是否与阻塞进程重复compare2=check(head2,temp);//检查进程是否与运行进程重复compare3=check(head3,temp);//检查进程是否与就绪进程重复if( !(compare1 && compare2 && compare3) && count<10 ){printf("已有进程中已有该名称进程,创建失败!");system("pause");return;}printf("\n请输入进程优先级(1-低,2-中,3-高):");scanf("%d",&temp->ppri);getchar();printf("\n请输入进程运行时间:");scanf("%d",&temp->pruntime);getchar();temp->pstatus=3;//将新创建进程放入就绪队列insert(head3,temp);
count++;system("pause");if(head2->next == NULL)run(head2,head3);
}void block(PCB *head1,PCB *head2,PCB *head3){//阻塞进程函数char name[10];PCB *p,*q;system("cls");printf("---------------阻塞进程---------------\n");printf("请输入你要阻塞的进程名称:");scanf("%s",name);getchar();p=head1;p=p->next;while(p){//在阻塞进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程已在阻塞队列中,不可重复放入\n");system("pause");return;}p=p->next;}p=head3->next;while(p){//在就绪进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程在就绪队列中,无法放入\n");system("pause");return;}p=p->next;}p=head2->next;while(p){//在运行进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程处于运行状态,准备将该进程放入阻塞队列\n");system("pause");p->pstatus=1;q=head1->next;while(q)q=q->next;q->next=p;head2->next=NULL;printf("已经将该进程放入阻塞队列,完成!\n");system("pause");run(head2,head3);//将执行进程阻塞,需要将cpu重新分配return;}p=p->next;}if(!p){printf("\n系统中无该进程\n");system("pause");return;}
}void wakeup(PCB *head1,PCB *head2,PCB *head3){//唤醒进程char name[10];PCB *p,*q;system("cls");printf("\n---------------唤醒进程----------------\n");printf("\n输入你要唤醒的进程名称:");scanf("%s",name);getchar();p=head1;p=p->next;while(p){//在阻塞进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程处于阻塞状态,准备将该进程放入就绪队列\n");system("pause");p->pstatus=3;q=head3->next;while(q)q=q->next;q->next=p;head2->next=NULL;printf("已经将该进程放入就绪队列,完成!\n");system("pause");return;}p=p->next;}	p=head2;p=p->next;while(p){//在运行进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程在运行队列中\n");system("pause");return;}p=p->next;}p=head3;p=p->next;while(p){//在就绪进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){printf("\n该进程在就绪队列中\n");system("pause");return;}p=p->next;}if(!p){printf("系统中无该进程名称\n");system("pause");return;}
}void stop(PCB *head1,PCB *head2,PCB *head3){//终止进程函数char name[10];PCB *p;system("cls");printf("\n---------------终止进程----------------\n");printf("\n输入你要终止的进程名称:");scanf("%s",name);getchar();p=head1->next;while(p){//在阻塞进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){Delete(head1,p);//调用删除结点函数
count--;printf("\n进程终止成功\n");system("pause");return;}p=p->next;}p=head2->next;while(p){//在运行进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){Delete(head2,p);//调用删除结点函数count--;
printf("\n进程终止成功\n");run(head2,head3);system("pause");return;}p=p->next;}p=head3->next;while(p){//在就绪进程中寻找pname为name的进程if(strcmp(p->pname,name)==0){Delete(head3,p);//调用删除结点函数count--;
printf("\n进程终止成功\n");system("pause");return;}p=p->next;}if(!p){printf("进程队列中无该进程\n");system("pause");}
}void show(PCB *head1,PCB *head2,PCB *head3){//显示队列进程int block=1,run=1,ready=1;PCB *p,*q;system("cls");p=head1;/*列出阻塞队列列表*/if(p->next==NULL){printf("阻塞队列中没有进程,请返回主界面创建进程\n");system("pause");}else{q=p->next;//指针指到第一个结点printf("\n--阻塞队列--\n");while(q){printf("%d)进程名:%s\n",block++,q->pname);printf("  进程优先级:%d\n",q->ppri);printf("  进程运行时间:%d\n",q->pruntime);q=q->next;}}printf("\n");p=head2;/*列出运行队列列表*/if(p->next==NULL){printf("运行队列中没有进程,请返回主界面创建进程\n");system("pause");}else{q=p->next;//指针指到第一个结点printf("\n--运行队列--\n");while(q){printf("%d)进程名:%s\n",run++,q->pname);printf("  进程优先级:%d\n",q->ppri);printf("  进程运行时间:%d\n",q->pruntime);q=q->next;}}printf("\n");p=head3;/*列出就绪队列列表*/if(p->next==NULL){printf("就绪队列中没有进程,请返回主界面创建进程\n");system("pause");}else{q=p->next;//指针指到第一个结点printf("\n--就绪队列--\n");while(q){printf("%d)进程名:%s\n",ready++,q->pname);printf("  进程优先级:%d\n",q->ppri);printf("  进程运行时间:%d\n",q->pruntime);q=q->next;}}printf("\n");printf("进程显示完毕");system("pause");
}void main(){//主函数PCB *head1,*head2,*head3;//head1为阻塞队列,head2为运行队列(单核),head3为就绪队列head1=(PCB*)malloc(sizeof(PCB));head2=(PCB*)malloc(sizeof(PCB));head3=(PCB*)malloc(sizeof(PCB));head1->next=NULL;//无节点,置空head2->next=NULL;head3->next=NULL;if(!head1 || !head2 || !head3)//只有有一个队列申请空间失败,则进入if{	printf("申请空间失败,退出!");system("pause");exit(0);}while(true){int choose;system("cls");menu();scanf("%d",&choose);switch(choose){case 0:exit(0);break;case 1:create(head1,head2,head3);break;//创建新进程放入就绪队列case 2:block(head1,head2,head3);break;//阻塞运行进程case 3:wakeup(head1,head2,head3);break;//唤醒阻塞进程case 4:stop(head1,head2,head3);break;//终止的进程可能位于某一个队列case 5:show(head1,head2,head3);break;//显示三个队列的进程default:printf("输入错误");break;}}
}

七、程序中使用的数据结构及符号说明:

进程名用 P1,P2 标识
优先级(1-低,2-中,3-高)
运行时间
状态(1-阻塞,2运行,3就绪)
指针:指向下一个 PCB。

typedef struct PCB{char pname[10];//进程名int ppri;//优先级 1-低,2-中,3-高int pruntime;//运行时间int pstatus;//运行状态 1-阻塞,2运行,3就绪struct PCB *next;//指针,指向下一个PCB
}PCB;
int count=0;//记录进程数目
PCB *head1,*head2,*head3;//head1为阻塞队列,head2为运行队列(单核),head3为就绪队列

八、调试程序时出现问题说明及解决的方法:

  1. 定义PCB时,优先级和运行状态的各数字表示不同的意义,混淆导致程序不按预想的结果输出。
    解决方法:重复对照上下文的数字,一个一个函数修正以求正确。
  2. 程序除了create、block、wakeup、stop、show函数,还需要run、insert、check、Delete函数辅助。
  3. 起初用一个队列描述PCB,无法实现run时先运行就绪队列的首节点,阻塞运行进程是无法将其放入阻塞队列的尾结点。
    解决方法:建立三个PCB队列,分别表示就绪队列、运行队列、阻塞队列,实现顺序。
  4. 函数使用参数时,不知道用&head还是*head。
    解决方法:复习C语言中的值传递和地址传递。
  5. 使用各函数时总是参数不够,无法实现预想功能。
    解决方法:个别函数需要三个参数变量,即head1、head2和head3。

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

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

相关文章

【算法分析与设计】翻转二叉树

题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例…

本地运行环境工具UPUPWANK(win)和Navicat数据库管理工具

UPUPWANK安装地址&#xff1a;https://www.upupw.net 1.进入UPUPWANK后点击一键开启 2.新增项目 这里请千万注意80端口&#xff0c;如果80端口被占用了&#xff0c;请记住去任务管理器关闭占用80端口的进程。不然就不会成功显示。&#xff08;笔者含泪警告&#xff0c;一晚上的…

多线程应用中的性能优化:创建合适的线程数

多线程应用中的性能优化&#xff1a;创建合适的线程数 在多线程应用中&#xff0c;为了降低延迟和提高吞吐量&#xff0c;我们可以采取两种主要策略&#xff1a;优化算法或者充分利用硬件性能。要发挥硬件的极致性能&#xff0c;就需要使用多线程来提高CPU或I/O的利用率。 由于…

TypeScript+Jest测试

1、初始化TypeScript工程 npm i -D typescript生成TypeScript工程配置 tsc --init代码目录 test └── src├── sum.test.ts└── sum.tssum.ts export function add(a: number, b: number): number {return a b; }sum.test.ts import { add } from ./sum;test(add …

Spring中的OAuth2

一. 什么是OAuth2 “Auth” 表示 “授权” Authorization “O” 是 Open 的简称&#xff0c;表示 “开放” 连在一起就表示 “开放授权”&#xff0c;OAuth2是一种开放授权协议。 二. OAuth2是什么 怎么用 OAuth2是目前最流行的授权协议&#xff0c;用来授权第三方应用&am…

信号的小波包能量谱计算(以轴承振动信号为例,Python环境)

小波分析是近30年来发展起来的数学分支&#xff0c;是Fourier分析划时代发展的结果&#xff0c;由法国工程师Morlet首先提出&#xff0c;后广泛应用于信号处理、图像处理与分析、地震勘探、故障诊断、自动控制等领域&#xff0c;小波就是小的波形&#xff0c;所谓“小”是指它具…

QT文件读写操作和内容提取

访问IO设备&#xff0c;需要先调用open()来设置正确的OpenMode(例如ReadOnly或ReadWrite) 打开设备后后&#xff0c;使用write() 或putChar() 写入数据到文件和设备&#xff0c;并通过调用read()&#xff0c;readLine() 或readAll() 进行读取&#xff1b;使用完设备后&#xf…

供应链攻击揭秘:识别、防范与应对

供应链攻击是网络安全领域的一种新兴威胁&#xff0c;它利用供应链中的漏洞对目标进行攻击。本文将介绍供应链攻击的概念、类型、危害&#xff0c;并通过具体案例阐述其影响&#xff0c;同时探讨如何防范供应链攻击&#xff0c;以提高人们对供应链攻击的认识和防范意识。 一、引…

3、Jenkins持续集成-Jenkins安装和插件管理

文章目录 一、Jenkins安装1. 安装JDK2. 获取jenkins安装包3. 安装包上传到服务器&#xff0c;进行安装4. 修改Jenkins配置&#xff08;1&#xff09;低版本Jenkins的rpm包&#xff08;2&#xff09;高版本Jenkins的rpm包 5. 启动Jenkins6. 打开浏览器访问7. 获取并输入admin账户…

【漏洞复现】netgear路由器 boarddataww 存在RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

HTML发展史

为什么要讲 HTML 发展史呢&#xff1f; 唐太宗告诉我们: 以铜为镜&#xff0c;可以正衣冠&#xff1b;以史为镜&#xff0c;可以知兴替&#xff1b;以人为镜&#xff0c;可以明得失。 那了解了 HTML 的发展史&#xff0c;可以知道什么呢&#xff1f; 答案是兼容 国内在 淘宝…

FDM3D打印系列——美纹纸遮挡喷漆

大家好&#xff0c;我是阿赵。   自从上次尝试了水补土和喷漆&#xff0c;发现效果不错之后&#xff0c;我就接着进行第二次的尝试了。   这次打印的模型是这个拳皇里面的卢卡尔&#xff0c;别看拍照好像很高大&#xff0c;其实这个模型很小的&#xff0c;只有10cm左右的高…

C#获取HTML源码

C#获取HTML源码 2024年03月23日记录 以前的那个从网上找到的方法, 在一些网站上用不了&#xff0c;如17K&#xff0c;取出来的是乱码&#xff0c;要么就是一坨JS&#xff0c;好像是用JS又重新加载了什么的 using System; using System.Collections.Generic; using System.We…

面试 Java 基础八股文十问十答第二十期

面试 Java 基础八股文十问十答第二十期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;HashMap 和 Concurre…

打造全网最全Doris面试题(100个问题2万字)

在大数据领域,Doris作为一款高性能、易扩展的MPP(Massively Parallel Processing)分析数据库,受到了越来越多企业的青睐。作为一名大数据架构师,了解Doris的核心特性和面试题是至关重要的。本文将为您提供一系列Doris面试题的参考答案,帮助您在面试中游刃有余,同时也为您…

PySide6-YOLO8目标检测、追踪可视化界面

目录 项目地址实现效果DetectTrack 项目地址 https://github.com/zhengjie9510/pyside-yolo 实现效果 Detect Track

windows安装ssh

一、下载ssh https://github.com/PowerShell/Win32-OpenSSH/releases/download/v8.1.0.0p1-Beta/OpenSSH-Win64.zip 二、安装ssh 解压到C:\Program Files\OpenSSH-Win64 配置环境变量 把 C:\Program Files\OpenSSH-Win64 加到path环境变量里面 C:\Program Files\OpenSSH-Win64&…

JDK1.8新特性——Stream流方法引用

文章目录 Stream流如何获取流水线Stream流中间方法Stream终结方法 方法引用引用静态方法引用成员方法引用构造方法类名引用成员方法引用数组构造方法 Stream流 Stream流是JDK8中提供的一种新特性 Stream流的使用步骤&#xff1a; 先得到Stream流&#xff0c;把数据放到流中使…

七、大模型-什么是Fine-tuning

好文推荐 推荐一篇比较透彻的介绍 对于深度学习模型中的 Fine-tuning&#xff08;微调&#xff09;操作&#xff0c;以下是详细介绍和原理说明&#xff1a; 什么是 Fine-tuning&#xff08;微调&#xff09;&#xff1f; Fine-tuning 是指在一个已经训练好的模型基础上&am…

Arcgis 导入经纬度坐标、导出经纬度坐标

目录 一、导入经纬度坐标 1、在excel中准备好经纬度坐标的数据表 2、将数据放入Acrgis的工作路径 3、在arcgis中添加数据 4、显示经纬度坐标点 5、导出为shp矢量文件 二、根据shp的经纬度坐标点导出成经纬度坐标 1、右键选择打开属性表 2、在属性表的菜单下拉栏里找到…