前言
操作系统系列博客的所有实验源自于课程"操作系统原理与实践检验"
,代码是参考老师给的"软件工程专业操作系统实验指导书"
文档后的改进版本。操作系统是计算机系统的核心,因此了解操作系统的设计和实现思路是必不可少的。了解操作系统的基本要求是:理解进程的概念,理解死锁,掌握银行家算法;掌握页式储存管理的实现原理以及页面置换法
实验目的
- 理解进程创建的相关理论
- 掌握进程创建的方法
- 掌握进程相关数据结构
实验内容
本实验针对操作系统中进程创建相关理论进行实验。要求实验者输入实验指导书提供的代码并进行测试。代码简化了进程创建的多个步骤和内容。进程的树形结构采用广义二叉树的方式进行储存
实验过程
定义进程控制块PCB(Process Control Block)
为了描述和控制进程的运行,系统为每个进程定义了一个进程控制块(PCB)。它是进程实体的一部分,是操作系统进程管理中最重要的数据结构,其主要包含以下信息:
- 进程标识符:在系统中唯一地标识一个进程。通常包括:
- 进程号
pid
- 父进程号
ppid
- 用户号
uid
。
- 进程号
- 处理机状态:处理器的状态通常由处理机的各种寄存器中的内容组成。PCB负责存放中断/阻塞/挂起时各个寄存器的值,当进程恢复执行时,进程可以从断点处恢复并继续运行。其数据结构包括:
- 通用寄存器
- 指令计数器
- 程序状态字PSW
- 用户栈指针。
- 进程调度信息:进程在调度过程中,系统需要记录进程的执行信息,以管理进程的运行,为进程分配CPU时间片。调度需要用到以下的信息:
- 进程状态(就绪/阻塞/挂起)
- 进程优先级(用于描述优先获得CPU时间片的级别的整数,高优先级的进程优先获得CPU时间片。通常情况下,该值越小优先级越高)
- 其他信息(等待时间、运行总时间等。用于记录进程执行的相关信息)
- 事件(描述进程挂起/阻塞的原因)
- 进程控制信息:用于记录进程执行所需要的资源信息,创建执行进程的程序信息以及进程锁和进程之间的通信信息。其数据结构包括:
- 程序和数据的地址(程序在内存和外存中的首地址)
- 进程同步和通信机制
- 资源列表(进程除CPU以外的所有资源)
- 链接指针(进程队列中指向下一个进程的PCB首地址)
定义进程控制块的代码如下:
1 | // 基础进程控制块(PCB) |
进程的创建
进程创建首先需要申请一个空白的PCB,获得唯一的进程ID,装载进程运行所需要的信息
为新进程分配内存和栈空间
初始化进程控制块:
- 初始化标识信息
- 初始化处理机状态信息
- 初始化处理机控制信息
将新进程插入就绪队列
将新进程插入进程树中,进程树用于用于描述进程家族关系。如下图1-1中可以看出,进程P1创建了进程P2、P3、P4、P5,而P2创建了P6、P7、P8。在进程的创建过程中,我们需要将每一个新进程都插入到进程树中,有了清晰的父子关系,资源继承、进程删除等操作将会十分方便
将新进程插入到进程总链中,该总链可以快速定位和查找进程
进程创建的代码如下:
1 | // 进程树根节点 |
代码汇总
PCB头文件
我们将PCB整理为一个头文件basicpcb.h
,并添加如下常用工具函数,也可以使用C++标准库中的函数
函数名称 | 作用介绍 |
---|---|
geterror |
获取错误信息 |
initerror |
初始化错误信息 |
substr |
获取字串 |
instr |
查找字符C在Str中的位置 |
strtoarray |
将Str字符串按照格式转化为string数组 |
basicpcb.h
代码如下:
1 | // 进程控制块PCB头文件 |
进程创建具体实现
我们在process.cpp
文件中实现进程的创建,并编写了main
函数进行测试
process.cpp
代码如下:
1 |
|
实验测试
编译并运行程序
g++ process.cpp -o process
使用
help
命令查看帮助使用
createpc
命令创建进程,使用showdetail
命令查看进程信息
总结
本次实验我们模拟了一次进程的创建,在模拟创建的过程中,我们了解了进程控制块的定义,进程之间的组织方式,如何将进程添加到进程树和进程总链中。在现在的操作系统中,进程的创建还需要加载静态和计算机硬件资源,这比我们自己做的实验要复杂的多。