进程管理
1. 进程和线程
1.1 进程
代码经过编译后,会生成可执行文件。当执行这个可执行文件时,它会被加载到内存中,接着CPU会执行程序中的指令。这个运行中的程序,就称之为进程(Process)。
在一个进程运行过程中,难免会去读磁盘、网络的IO,这个时间相对是比较长的。此时,CPU 不需要阻塞等待数据的返回,而是去执行另外的进程。当硬盘数据返回时,CPU 会收到个中断,于是 CPU 再继续运行这个进程。
1.1.1 进程的状态
进程不是一直运行的,一个进程至少具备五种基本状态,即创建状态、运行状态、就绪状态、阻塞状态、结束状态。

- NULL -> 创建状态:一个新进程被创建时的第一个状态;
- 创建状态->就绪状态:当进程被创建完成并初始化后,一切就绪准备运行时,变为就绪状态,这个过程是很快的;
- 就绪态->运行状态:处于就绪状态的进程被操作系统的进程调度器选中后,就分配给 CPU 正式运行该进程;
- 运行状态->结束状态:当进程已经运行完成或出错时,会被操作系统作结束状态处理;
- 运行状态->就绪状态:处于运行状态的进程在运行过程中,由于分配给它的运行时间片用完,操作系统会把该进程变为就绪态,接着从就绪态选中另外一个进程运行;
- 运行状态->照塞状态:当进程请求某个事件且必须等待时,例如请求1/0事件;
- 阻塞状态->就绪状态:当进程要等待的事件完成时,它从阻塞状态变到就绪状态;
如果有大量处于阻塞状态的进程,进程可能会占用着物理内存空间。 在虚拟内存管理的操作系统中,通常会把阻塞状态的进程的物理内存空间换出到硬盘,等需要再次运行的时候,再从硬盘换入到物理内存。
通过sleep、用户主动挂起(linux的 ctrl + z)也可以触发进程的挂起
此时就会新增两个状态:
阻塞挂起状态:进程在外存(硬盘)并等待某个事件的出现
就绪挂起状态:进程在外存(硬盘),但只要进入内存,即刻立刻运行

进程管理-七种进程状态
1.1.2 进程的控制结构
进程控制块(process control block,PCB) 是用来描述进程的数据结构。PCB是进程存在的唯一标识。
PCB主要包括以下内容:
- 进程描述信息
- 进程标识符:标识各个进程,每个进程都有一个并且唯一的标识符;
- 用户标识符:进程归属的用户,用户标识符主要为共享和保护服务;
- 进程控制和管理信息
- 进程当前状态,如 new、ready、running、waiting 或 blocked 等;
- 进程优先级:进程抢占 CPU 时的优先级;
- 资源分配清单
- 有关内存地址空间或虚拟地址空间的信息,所打开文件的列表和所使用的/O设备信息。
- CPU 相关信息
- CPU 中各个寄存器的值,当进程被切换时,CPU的状态信息都会被保存在相应的PCB中,以便进程重新执行时,能从断点处继续执行。
多个PCB通过链表的方式进行组织,并存储在内核空间,把具有相同状态的进程链在一起,组成各种队列。如:就绪队列、阻塞队列。
1.2.3 进程的控制
1)创建进程
操作系统允许一个进程创建另一个进程,而且允许子进程继承父进程所拥有的资源。 过程如下:
- 申请一个空白的 PCB 并填充信息;
- 为该进程分配运行时资源,比如内存资源;
- 将PCB 插入到就绪队列,等待被调度运行;
2)终止进程
进程可以有3种终止方式:正常结束、异常结束以及外界干预(信号 kill 掉)。
当子进程被终止时,其在父进程处继承的资源应当还给父进程。而当父进程被终止时,该父进程的子进程就变为孤儿进程,会被1号进程收养,并由1号进程对它们完成状态收集工作。
终止进程的过程如下:
- 查找需要终止的进程的 PCB;
- 如果处于执行状态,则立即终止该进程的执行,然后将 CPU 资源分配给其他进程;
- 如果其还有子进程,则应将该进程的子进程交给 1号进程接管;
- 将该进程所拥有的全部资源都归还给操作系统;
- 将其从 PCB 所在队列中删除;
3)阻塞进程
当进程需要等待某一事件完成时,它可以调用阻塞语句把自己阻塞等待。而一旦被阻塞等待,它只能由另一个进程唤醒。
阻塞进程的过程如下:
- 找到将要被阻塞进程标识号对应的 PCB;
- 如果该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停止运行;
- 将该 PCB 插入到阻塞队列中去;
4)唤醒进程
进程由运行转变为阻塞状态是由于进程必须等待某一事件的完成,所以处于阻塞状态的进程是绝对不可能叫醒自己的。
如果某进程正在等待IO事件,需由别的进程发消息给它,则只有当该进程所期待的事件出现时,才由发现者进程用唤醒语句叫醒它。
唤醒进程的过程如下:
- 在该事件的阻基队列中找到相应进程的 PCB;
- 将其从阻塞队列中移出,并置其状态为就绪状态;
- 把该 PCB 插入到就绪队列中,等待调度程序调度;
进程的阻塞和唤醒是一对功能相反的语句,如果某个进程调用了阻塞语句,则必有一个与之对应的唤醒语句。