计算机操作系统实验之模拟进程管理(C语言)

计算机操作系统实验之模拟进程管理(C语言)利用 C 语言模拟实现操作系统中的进程管理

这星期开始上计算机操作系统的实验课,打算把每个实验的内容和思路记录一下

实验目的

1、 理解进程的概念,明确进程和程序的区别。

2、 理解并发执行的实质。

3、 掌握进程的创建、睡眠、撤销等进程控制方法。

实验内容与基本要求

用C,C++等语言编写程序,模拟实现创建新的进程;查看运行进程;换出某个进程;杀死进程等功能。

实验报告内容

1.进程、进程控制块等的基本原理

a.为了能使程序并发执行,并且可以对并发执行的程序加以描述和控制,引入了“进程”的概念。它是资源分配和独立运行的基本单位。

b.进程控制块(PCB)是操作系统为进程配置的一个专门的数据结构。系统利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程。

进程PCB可以包含

/* |进程ID| |进程优先级| |进程大小(进程执行时间| |进程内容| |进程状态| |指针| */ 

2.进程过程图

img_1

以传统菜单的形式呈现功能。

1.创建新的进程 2.查看运行进程”

3.换出某个进程 4.杀死运行进程”

5.唤醒某个进程 6.退出程序 “

实现思路及功能分析

系统利用进程控制块(Process Control Block,PCB)来描述系统的基本情况和活动过程,要进行进程管理,实际上就是在操作进程的PCB。因此要求模拟进程管理,首先要模拟出PCB的结构,再实现它的创建、撤销等操作。

一般来说,进程拥有三种基本状态:就绪、执行、阻塞。在引入了挂起原语操作后,还会细分为活动就绪、静止就绪、活动阻塞、静止阻塞。在我的理解中,活动与静止的区别就是,活动时进程是在主存中的,而静止时进程已经被调到了辅存里。

在单处理机系统中,只有一个进程处于执行状态,而在多处理机系统中,能有多个进程处于执行状态。因此在这里我们不将执行状态与就绪状态特别区分开来,只设置两个链表,一个链表用于保存处于执行(或就绪)状态的进程,一个链表用于保存处于阻塞状态的进程。

当然,如果想模拟单处理机系统的话,也可以将处于就绪状态链表的第一个结点默认设置为执行状态,当有优先度更高的进程时,让它成为执行状态,插入链表头部,原有的第一个结点转为就绪状态即可。但是本实验中不涉及优先级调度的算法,所以就简化处理了。

同样,我们模拟内存的大小,例如理论上可以同时运行20个进程,那么将处于执行状态的进程转为阻塞状态时,可以看做把它转移到了辅存中。但是不区分活动阻塞、静止阻塞,只是简单地设置成运行进程个数的变化。

总的来说,我们这次试验的思路是

  • 设置两个单链表,一个用于存储运行的进程,一个用于存储阻塞状态的进程
  • 默认内存中可以存放最多20个进程,将处于运行队列的进程看作在内存中,阻塞状态不在内存中
  • 进程创建,则去申请内存空间,填写完进程信息后直接加入运行队列
  • 杀死进程,则将进程从运行队列中删除,并直接释放
  • 进程的换出与唤醒,就是让进程在运行队列与阻塞队列之间转换(进程自己的状态也发生改变)
  • 为了操作简便,额外写了几个辅助函数来使用

流程图

img_2

全部代码

工程图

img_2

ProcessControl.h

// // ProcessControl.h // ProcessControlTest // // Created by Apple on 2019/10/13. // Copyright © 2019 Yao YongXin. All rights reserved. // #ifndef ProcessControl_h #define ProcessControl_h #include  
     #include  
     #include  
     //最大内存的大小 #define MAX_SIZE 20 //线程状态:运行(就绪) 阻塞 enum process_type{ 
    process_type_running = 1000, process_type_block = -1000, process_type_ready = 500 }; //进程控制块结构体 typedef struct PCB_Type{ 
    //进程的id int pid; //进程的优先级 int priority; //进程大小(执行时间) int size; //进程内容 char content[20]; //进程的状态 执行 阻塞 int state; //下一个要执行的进程 struct PCB_Type *next; }PCB; //创建新的进程 void create(PCB *running_list,PCB *block_list,int *size); //查看运行进程 void show_running(PCB *running_list); //换出某个进程 void change(PCB *running_list,PCB *block_list,int *size); //杀死运行进程 void killed(PCB *running_list,int *size); //唤醒某个进程 void wake_up(PCB *running_list,PCB *block_list,int *size); //判断在运行(就绪)队列中是否存在有该pid值的进程 0->不存在 1->存在 int exist_in_running(PCB *running_list,int pid); //判断在阻塞队列中是否存在有该pid值的进程 0->不存在 1->存在 int exist_in_block(PCB *block_list,int pid); //通过pid寻找进程的位置(返回其前一个结点的地址 PCB *find(PCB *list,int pid); #endif /* ProcessControl_h */ 

ProcessControl.c

// // ProcessControl.c // ProcessControlTest // // Created by Apple on 2019/10/13. // Copyright © 2019 Yao YongXin. All rights reserved. // #include "ProcessControl.h" //创建新的进程 void create(PCB *running_list,PCB *block_list,int *size){ 
    if (*size >= MAX_SIZE) { 
    //内存不足,无法创建 printf("内存不足,无法创建新的进程\n"); return; } //申请一个内存控制块的空间 PCB *p = (PCB *)malloc(sizeof(PCB)); assert(p != NULL); //设置该控制块的id值 int pid; printf("请输入新进程的pid:\n"); scanf("%d",&pid); //判断pid值是否重复 if (exist_in_running(running_list, pid)) { 
    printf("该值已存在!\n"); return; } if (exist_in_block(block_list, pid)) { 
    printf("该值已存在!\n"); return; } //没重复,保存 p->pid = pid; //设置该控制块的其他值 printf("请输入新进程的优先级:\n"); scanf("%d",&p->priority); printf("请输入新进程的大小:\n"); scanf("%d",&p->size); printf("请输入新进程的内容:\n"); scanf("%s",p->content); p->state = process_type_running; p->next = NULL; //放入就绪队列中 PCB *s = running_list; while (s->next != NULL) { 
    s = s->next; } s->next = p; //进程数量+1 *size = *size + 1; } //查看运行进程 void show_running(PCB *running_list){ 
    PCB *s = running_list->next; if (s == NULL) { 
    printf("没有正在运行的进程\n"); return; } while (s != NULL) { 
    printf("进程id:%d\n",s->pid); printf("进程优先级:%d\n",s->priority); printf("进程大小:%d\n",s->size); printf("进程内容:%s\n",s->content); printf("___________\n"); s = s->next; } } //换出某个进程 void change(PCB *running_list,PCB *block_list,int *size){ 
    if (*size == 0) { 
    printf("无可换出的进程\n"); return; } int pid; printf("请输入需要换出进程的id:\n"); scanf("%d",&pid); //查看该线程是否在就绪队列中 if (exist_in_running(running_list, pid)) { 
    //存在,找到该线程的位置(返回的是前一个结点的地址 PCB *s = find(running_list, pid); //修改线程状态 s->next->state = process_type_block; //将该线程存入阻塞队列中 //寻找插入位置 PCB *p = block_list; while (p->next != NULL) { 
    p = p->next; } //插入 p->next = s->next; //将该线程从就绪队列中移出 s->next = s->next->next; //将该线程的next重置为空 p->next->next = NULL; *size = *size - 1; printf("成功换出\n"); }else{ 
    printf("该线程不存在或已处于阻塞状态\n"); } } //杀死运行进程 void killed(PCB *running_list,int *size){ 
    if (*size == 0) { 
    printf("无可杀死的进程\n"); return; } int pid; printf("请输入要杀死的进程id:\n"); scanf("%d",&pid); //判断该进程是否存在 if (exist_in_running(running_list, pid)) { 
    //存在,找到该线程的位置(返回的是前一个结点的地址 PCB *s = find(running_list, pid); //保存该线程的地址,用于释放 PCB *thisThread = s->next; //将该线程从就绪队列移出 s->next = s->next->next; *size = *size - 1; //直接释放掉该线程 free(thisThread); printf("成功杀死\n"); }else{ 
    printf("该线程不存在或已处于阻塞状态\n"); } } //唤醒某个进程 void wake_up(PCB *running_list,PCB *block_list,int *size){ 
    PCB *s = block_list; if (s->next == NULL) { 
    printf("没有可唤醒的线程\n"); return; } int pid; printf("请输入要唤醒的进程id:\n"); scanf("%d",&pid); //判断该进程是否存在 if (exist_in_block(block_list, pid)) { 
    //存在,查找到该线程的位置(返回的是前一个结点的地址 s = find(block_list, pid); //修改线程状态 s->next->state = process_type_running; //将该线程存入就绪队列中 //寻找插入位置(最后一位) PCB *p = running_list; while (p->next != NULL) { 
    p = p->next; } //插入 p->next = s->next; //将该线程从阻塞队列中取出 s->next = s->next->next; //将该线程的next值重置为null p->next->next = NULL; *size = *size + 1; printf("唤醒成功\n"); }else{ 
    printf("该线程不存在\n"); } } //判断在就绪队列中是否存在有该pid值的进程 0->不存在 1->存在 int exist_in_running(PCB *running_list,int pid){ 
    int result = 0; PCB *s = running_list->next; //遍历执行状态的链表 while (s != NULL) { 
    if (s->pid == pid) { 
    //存在,直接返回 result = 1; break; } s = s->next; } return result; } //判断在阻塞队列中是否存在有该pid值的进程 0->不存在 1->存在 int exist_in_block(PCB *block_list,int pid){ 
    int result = 0; //遍历阻塞状态的链表 PCB *s = block_list->next; while (s != NULL) { 
    if (s->pid == pid) { 
    //存在,直接返回 result = 1; break; } s = s->next; } return result; } //通过pid寻找进程的位置(返回其前一个结点的地址 PCB *find(PCB *list,int pid){ 
    PCB *s = list; while (s->next != NULL) { 
    if (s->next->pid == pid) { 
    return s; } s = s->next; } return NULL; } 

main.c

// // main.c // ProcessControlTest // // Created by Apple on 2019/10/13. // Copyright © 2019 Yao YongXin. All rights reserved. // #include "ProcessControl.h" void showLine(){ 
    printf("\n"); } int main(int argc, const char * argv[]) { 
    //运行(就绪)队列(头结点不储存信息) PCB *running_list = (PCB *)malloc(sizeof(PCB)); running_list->next = NULL; //阻塞队列(头结点不储存信息) PCB *block_list = (PCB *)malloc(sizeof(PCB)); block_list->next = NULL; //当前运行的线程数量 int storage_number = 0; int choose = 1; while (choose) { 
    //展示菜单 showLine(); printf("* 进程演示系统 *\n"); showLine(); printf("1.创建新的进程 2.查看运行进程\n"); printf("3.换出某个进程 4.杀死运行进程\n"); printf("5.唤醒某个进程 6.退出程序 \n"); showLine(); printf("请选择(1~6):\n"); scanf("%d",&choose); switch (choose) { 
    case 1: //创建新的进程 create(running_list, block_list, &storage_number); break; case 2: //查看运行进程 show_running(running_list); break; case 3: //换出某个进程 change(running_list, block_list, &storage_number); break; case 4: //杀死运行进程 killed(running_list, &storage_number); break; case 5: //唤醒某个进程 wake_up(running_list, block_list, &storage_number); break; case 6: return 0; default: printf("没有这个选项!\n"); break; } } return 0; } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/219860.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午9:43
下一篇 2026年3月17日 下午9:44


相关推荐

  • datagrip 2021.11.4 激活_最新在线免费激活

    (datagrip 2021.11.4 激活)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月28日
    41
  • SpringBoot整合Quartz定时任务(持久化到数据库)

    背景最近在做项目,项目中有个需求:需要使用定时任务,这个定时任务需要即时生效。查看Quartz官网之后发现:Quartz提供两种基本作业存储类型:RAMJobStore:RAM也就是内存,默认情况下Quartz会将任务调度存在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,但程序崩溃或者重新发布的时候,所有运行信息都会丢失JDBC作业存储:存到数据库…

    2022年4月9日
    82
  • C语言if语句的基本用法

    C语言if语句的基本用法C语言if语句的基本用法一、if…1.一般形式:if(表达式){语句;}表达式:a,用非0值表示真,用0表示真;b,if(flag)相当于if(1==flag)c,浮点数无法与0比较,只能用近似的值比较;例:(1e-6)相当于1×10的-6次方;2.用于单分支选择结构;3.如含有交叉关系,使用并列的if语句;例:输出两个整数中的最大值#inclu…

    2022年5月19日
    45
  • 虚拟机繁忙的解决办法

    虚拟机繁忙的解决办法1 按 win R 组合键 进入 运行 2 写入 msconfig 按回车键 3 进入 系统配置 选中 服务 勾选左下角 隐藏所有 Microsoft 服务 再点击 全部禁用 点击 应用 4 再打开 服务 边上的 启动 选项 打开 点击任务管理器 5 在列出的启动项上 找到 VMware 点击右键 选中 禁用 禁止全部启动项 6 关闭 任务管理器 返回 系统配置 界面下点击 确定 依据提示重启电脑 7 电脑重启之后 再次按照上面流程启动所有服务 VMware 就可以正常启动了

    2026年3月17日
    2
  • c++ sort 二维数组排序_二维数组升序排列

    c++ sort 二维数组排序_二维数组升序排列以往遇到行排列问题(按每行的字典序排序)的时候,总是使用结构体来进行排序,但是如何使用二维数组来达到同样的效果呢?实验内容:利用二维数组进行“三级排序”测试1:使用c++内置的普通型二维数组#include<algorithm>#include<iostream>usingnamespacestd;boolcmp(inta[],intb[]){ …

    2022年8月12日
    14
  • 床长人工智能教程 下载_人工智能

    床长人工智能教程 下载_人工智能目录请先点击下面查看序言序言1神经网络与深度学习1.1介绍神经网络1.1.1什么是神经网络1.1.2监督学习型神经网络1.1.3什么使深度学习火起来了1.2神经网络基础1.2.1如何将待预测数据输入到神经网络中1.2.2神经网络是如何进行预测的1.2.3神经网络如何判断自己预测得是否准确1

    2026年2月7日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号