【Linux手册】进程的状态:从创建到消亡的“生命百态”
目录
前言
操作系统进程状态
运行状态
阻塞状态
挂起状态
Linux中具体的进程状态
R(running)运行状态
S(sleeping)阻塞状态
D(disk sleep)磁盘休眠状态
T(stopped)和t(tracing stop)
X(dead)终止状态
Z(zombie)僵尸状态
僵尸进程的危害
前言
我们在运行可执行程序形成进程后,操作系统要对多个进程进行管理,根据进程的状态对进程分类,不同类型的进程有不同的处理方案,下面将对不同进程的特点进行介绍。
操作系统进程状态
以上是进程状态之间的相互转化过程,下面将详细围绕三个状态展开:运行状态,阻塞状态,挂起状态。
运行状态
运行状态就是正在运行的进程,很好理解;
问题是:CPU只有一个,但是进程有多个,可能多个进程都处于运行状态,操作系统是如何平衡这些进程的,如何保证这些进程都能够持续运行???
有多个进程都要运行,那就意味着在一段时间内每个进程都要得到执行。当然因为CPU只有一个所以在一个时间点只能对运行一个进程。
在操作系统中有一个概念叫做运行队列,所有处于运行状态进程的PCB数据结构体对象都在这个队列中排队,一个个的运行;排队的先后顺序是根据进程的优先级决定的。
在进程中有一个时间片的概念,时间片可以保证每个进程在CPU中运算,处理的时间差不多,是每个进程都有机会执行。
CPU对进程依次进行处理,那为什么我并没有感觉到我打开的程序有卡顿的情况???这是初学者经常会出现的误区,这是因为CPU计算处理的速度太快了,人根本感知不到。
阻塞状态
阻塞状态很形象,不明事宜进程被阻塞了,不能再继续运行。出现阻塞状态有很多原因通常是因为: I/O 操作完成、等待用户输入、等待资源分配。就是进程处于等待状态,没有处在运行队列中,即使CPU空闲也无法对这样的进程进行计算,处理。
处于阻塞状态的进程存放在哪里???
操作系统对与软硬件管理的基础是:先描述,再组织。操作系统也要对硬件进行管理,所以操作系统中理应存在描述硬件信息的结构体对象。所以处于阻塞状态的进程放在对应外设(等待从那里读取数据)结构体对象的等待队列中。
挂起状态
常见的挂起状态是阻塞挂起状态。
阻塞挂起状态:当操作系统中有多个进程在同时加载,计算机中内存不足时,操作系统就会将一些处于阻塞状态的进程的信息,数据,PCB结构体对象都置换到外设(硬盘)中去,来使得计算机中空出一些内存继续进行运算,当一些进程执行完后释放空间又够了,再将数据从外设加载到内存中让进程继续执行。信息被拷贝到外设的进程就称为处于挂起状态的进程。
Linux中具体的进程状态
上面介绍了操作系统中进程状态的总体划分,下面以Linux为例详细介绍以下Linux下的进程状态。
*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {
"R (running)", /*0 */
"S (sleeping)", /*1 */
"D (disk sleep)", /*2 */
"T (stopped)", /*4 */
"t (tracing stop)", /*8 */
"X (dead)", /*16 */
"Z (zombie)", /*32 */
}
以上是Linux内核中定义的进程状态有7种:R(running)运行状态,S(sleeping)阻塞状态或浅度睡眠,D(disk sleep)深度睡眠,T(stopped)和t(tracing stop)暂停状态,X(dead)死亡状态,Z(zombie)僵尸状态。下面对这7种进程状态特点进行一一解释。
R(running)运行状态
依旧是将处于运行状态的进程放入到运行队列中进行调用,与前面说的一样没有特别之处。
S(sleeping)阻塞状态
也叫浅度睡眠状态,等待一些外设或I/O,用户指令......无法继续向后执行下去。
在上面谈到挂起状态:当内存不足时,操作系统会将一些进程的代码和数据以及PCB对象从内存置换到外设来空出内存供其他进程使用,被挂起的进程通常是处于阻塞状态的进程。
但是如果被挂起的进程正在等待磁盘信息的写入,等着磁盘告诉它是否写入成功的时候,突然该进程被挂起了,那磁盘内容是否写入成功就没人知道了,那数据如果没有写入成功还不知道,数据不久丢失了吗???
使得确实是这样的,所以操作系统有新增了一个状态D(disk sleep);
D(disk sleep)磁盘休眠状态
将正在等待磁盘写入或高I/O时才会出现,处于这种状态的进程不能被进程杀掉或挂起。
D状态的时间很短,一般在查进程状态时一般看不到这种状态,如果看到了说明磁盘现在写入的压力很大,很有可能操作系统快挂了。
T(stopped)和t(tracing stop)
T(stopped)和t(tracing stop)两个都表示暂停状态,只不过暂停的原因是不一样的。此处将其看作一样的。
暂停状态和阻塞状态有什么区别呢???他们不都是停止运行吗???
其主要区别在于暂停的原因是什么;阻塞状态的进程是在等待资源就绪,而处于暂停状态的进程是用户操作的,比如kill -19 +PID让进程暂停,kill -18 +PID让进程继续;还有gdb在进行调试的时候停止在一个断点上也是处于等待状态。
X(dead)终止状态
终止状态,毫无疑问程序运行结束后的状态,程序运行结束后会放到垃圾回收队列里面,等待释放。
Z(zombie)僵尸状态
我们知道每一个进程都有父进程,在命令行上打开的可执行程序也有父进程。在打开命令行时操作系统会自动将命令行解释器加载到内存中形成一个进程,所以当使用命令行打开其他程序时,命令行解释器就是它们的父进程。
当一个进程在进入终止状态之前,不会立即进入到垃圾回收队列中,而是先维护一会进程的属性状态即PCB结构体对象,让与其有关的进程(父进程)知道该进程要被释放了,很容易理解当一个进程要结束了必须要让操作系统知道,否则一个进程都结束了,而操作系统不知道,那操作系统还怎么管理进程。处于维护进程状态,等待子进程获取其状态信息的进程就处于僵尸进程,即快要死了,但还没死。
进程推出前,如果都进程没有主动获取子进程的相关信息,子进程就会一直处于Z状态直到父进程来获取其进程信息。
那如果父进程先子进程结束,怎么办???
如果父进程先结束,那么子进程就会称为孤儿进程,子进程的父进程将变成操作系统,被操作系统领养,操作系统直到关机一直都在。
僵尸进程的危害
- 进程推出状态要一直维护,直到父进程来获取进程的相关信息;
- 父进程一直不来获取子进程的相关信息,PCB就需要一直维护,也需要一直保持Z状态;
- 如果一直不回收子进程就会导致PCB长时间占用内存,导致内存泄漏。