版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34827674/article/details/107305756
进程的控制结构
在操作系统中,是用进程控制块(process control block,PCB)数据结构来描述进程的。
知乎搜 PCB 的提示
打住打住,我们是个正经的人,怎么会去看那些问题呢?是吧,回来回来。
PCB 是进程存在的唯一标识,这意味着一个进程的存在,必然会有一个 PCB,如果进程消失了,那么 PCB 也会随之消失。
PCB 具体包含什么信息呢?
进程描述信息:
-
进程标识符:标识各个进程,每个进程都有一个并且唯一的标识符;
-
用户标识符:进程归属的用户,用户标识符主要为共享和保护服务;
进程控制和管理信息:
-
进程当前状态,如 new、ready、running、waiting 或 blocked 等;
-
进程优先级:进程抢占 CPU 时的优先级;
资源分配清单:
-
有关内存地址空间或虚拟地址空间的信息,所打开文件的列表和所使用的 I/O 设备信息。
CPU 相关信息:
-
CPU 中各个寄存器的值,当进程被切换时,CPU 的状态信息都会被保存在相应的 PCB 中,以便进程重新执行时,能从断点处继续执行。
可见,PCB 包含信息还是比较多的。
每个 PCB 是如何组织的呢?
通常是通过链表的方式进行组织,把具有相同状态的进程链在一起,组成各种队列。比如:
-
将所有处于就绪状态的进程链在一起,称为就绪队列;
-
把所有因等待某事件而处于等待状态的进程链在一起就组成各种阻塞队列;
-
另外,对于运行队列在单核 CPU 系统中则只有一个运行指针了,因为单核 CPU 在某个时间,只能运行一个程序。
那么,就绪队列和阻塞队列链表的组织形式如下图:
就绪队列和阻塞队列
除了链接的组织方式,还有索引方式,它的工作原理:将同一状态的进程组织在一个索引表中,索引表项指向相应的 PCB,不同状态对应不同的索引表。
一般会选择链表,因为可能面临进程创建,销毁等调度导致进程状态发生变化,所以链表能够更加灵活的插入和删除。
进程的控制
我们熟知了进程的状态变迁和进程的数据结构 PCB 后,再来看看进程的创建、终止、阻塞、唤醒的过程,这些过程也就是进程的控制。
01 创建进程
操作系统允许一个进程创建另一个进程,而且允许子进程继承父进程所拥有的资源,当子进程被终止时,其在父进程处继承的资源应当还给父进程。同时,终止父进程时同时也会终止其所有的子进程。
创建进程的过程如下:
-
为新进程分配一个唯一的进程标识号,并申请一个空白的 PCB,PCB 是有限的,若申请失败则创建失败;
-
为进程分配资源,此处如果资源不足,进程就会进入等待状态,以等待资源;
-
初始化 PCB;
-
如果进程的调度队列能够接纳新进程,那就将进程插入到就绪队列,等待被调度运行;
02 终止进程
进程可以有 3 种终止方式:正常结束、异常结束以及外界干预(信号 kill
掉)。
终止进程的过程如下:
-
查找需要终止的进程的 PCB;
-
如果处于执行状态,则立即终止该进程的执行,然后将 CPU 资源分配给其他进程;
-
如果其还有子进程,则应将其所有子进程终止;
-
将该进程所拥有的全部资源都归还给父进程或操作系统;
-
将其从 PCB 所在队列中删除;
03 阻塞进程
当进程需要等待某一事件完成时,它可以调用阻塞语句把自己阻塞等待。而一旦被阻塞等待,它只能由另一个进程唤醒。
阻塞进程的过程如下:
-
找到将要被阻塞进程标识号对应的 PCB;
-
如果该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停止运行;
-
将该 PCB 插入的阻塞队列中去;
04 唤醒进程
进程由「运行」转变为「阻塞」状态是由于进程必须等待某一事件的完成,所以处于阻塞状态的进程是绝对不可能叫醒自己的。
如果某进程正在等待 I/O 事件,需由别的进程发消息给它,则只有当该进程所期待的事件出现时,才由发现者进程用唤醒语句叫醒它。
唤醒进程的过程如下:
-
在该事件的阻塞队列中找到相应进程的 PCB;
-
将其从阻塞队列中移出,并置其状态为就绪状态;
-
把该 PCB 插入到就绪队列中,等待调度程序调度;
进程的阻塞和唤醒是一对功能相反的语句,如果某个进程调用了阻塞语句,则必有一个与之对应的唤醒语句。