计算机操作系统实验一模拟进程管理(C语言)
这星期开始上计算机操作系统的实验课,打算把每个实验的内容和思路记录一下
实验目的
1、 理解进程的概念,明确进程和程序的区别。
2、 理解并发执行的实质。
3、 掌握进程的创建、睡眠、撤销等进程控制方法。
实验内容与基本要求
用C,C++等语言编写程序,模拟实现创建新的进程;查看运行进程;换出某个进程;杀死进程等功能。
实验报告内容
1.进程、进程控制块等的基本原理
a.为了能使程序并发执行,并且可以对并发执行的程序加以描述和控制,引入了“进程”的概念。它是资源分配和独立运行的基本单位。
b.进程控制块(PCB)是操作系统为进程配置的一个专门的数据结构。系统利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程。
进程PCB可以包含
/* |进程ID| |进程优先级| |进程大小(进程执行时间| |进程内容| |进程状态| |指针| */
2.进程过程图

以传统菜单的形式呈现功能。
1.创建新的进程 2.查看运行进程”
3.换出某个进程 4.杀死运行进程”
5.唤醒某个进程 6.退出程序 “
实现思路及功能分析
系统利用进程控制块(Process Control Block,PCB)来描述系统的基本情况和活动过程,要进行进程管理,实际上就是在操作进程的PCB。因此要求模拟进程管理,首先要模拟出PCB的结构,再实现它的创建、撤销等操作。
一般来说,进程拥有三种基本状态:就绪、执行、阻塞。在引入了挂起原语操作后,还会细分为活动就绪、静止就绪、活动阻塞、静止阻塞。在我的理解中,活动与静止的区别就是,活动时进程是在主存中的,而静止时进程已经被调到了辅存里。
在单处理机系统中,只有一个进程处于执行状态,而在多处理机系统中,能有多个进程处于执行状态。因此在这里我们不将执行状态与就绪状态特别区分开来,只设置两个链表,一个链表用于保存处于执行(或就绪)状态的进程,一个链表用于保存处于阻塞状态的进程。
当然,如果想模拟单处理机系统的话,也可以将处于就绪状态链表的第一个结点默认设置为执行状态,当有优先度更高的进程时,让它成为执行状态,插入链表头部,原有的第一个结点转为就绪状态即可。但是本实验中不涉及优先级调度的算法,所以就简化处理了。
同样,我们模拟内存的大小,例如理论上可以同时运行20个进程,那么将处于执行状态的进程转为阻塞状态时,可以看做把它转移到了辅存中。但是不区分活动阻塞、静止阻塞,只是简单地设置成运行进程个数的变化。
总的来说,我们这次试验的思路是
- 设置两个单链表,一个用于存储运行的进程,一个用于存储阻塞状态的进程
- 默认内存中可以存放最多20个进程,将处于运行队列的进程看作在内存中,阻塞状态不在内存中
- 进程创建,则去申请内存空间,填写完进程信息后直接加入运行队列
- 杀死进程,则将进程从运行队列中删除,并直接释放
- 进程的换出与唤醒,就是让进程在运行队列与阻塞队列之间转换(进程自己的状态也发生改变)
- 为了操作简便,额外写了几个辅助函数来使用
流程图

全部代码
工程图

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
