进程的状态

  • Post author:
  • Post category:其他


转载自:博学谷

一、进程状态

在三态模型中,进程状态分为三个基本状态,即

运行态,就绪态,阻塞态

在五态模型中,进程分为

新建态、终止态,运行态,就绪态,阻塞态

通过fork()创建进程,然后该进程进入就绪态,通过进程调度(进程优先级越高,调度该进程的可能性越大),进程进入运行态,当该进程的时间片到时,进程重新回到就绪态。该进程在运行态时,若该进程的子进程结束了,但是父进程还在,那么父进程就是个僵尸进程,那么它被终止之后就死亡了,其不再能够复活;该进程在运行态时,若进程执行完毕或者接收到(内核发送的)SIGSTOP和SIGTSTP信号,就进入到停止态,停止态若要被唤醒到就绪态,就要接收到SIGCONT信号。

不可中断等待态和可中断等待态区别:该进程是否可以被暂停。

Q:怎么表示父进程和子进程?

A:除了进程0以外的所有进程都是由其他进程使用系统调用fork创建的,这里调用fork创建新进程的进程即为父进程,而相对应的为其创建出的进程则为子进程,所以子进程是由父进程创建的,一个子进程只有一个父进程,但一个父进程可以有多个子进程。

#include<unistd.h>
pid_t fork(void);
//返回值:子进程中返回0,父进程返回子进程id,出错返回-1

其中:若上面代码为一段可运行的程序,运行该程序的为父进程,然后fork()创建了一个子进程,子进程的返回值为0, 父进程返回子进程id。


①TASK_RUNNING:

进程正在被CPU执行。当一个进程刚被创建时会处于TASK_RUNNABLE,表示己经准备就绪,正等待被调度。


②TASK_INTERRUPTIBLE(可中断):

进程正在睡眠(也就是说它被阻塞)等待某些条件的达成。一旦这些条件达成,内核就会把进程状态设置为运行。处于

此状态的进程也会因为接收到信号而提前被唤醒



比如给一个TASK_INTERRUPTIBLE状态的进程发送SIGKILL信号,这个进程将先被唤醒(进入TASK_RUNNABLE状态),然后再响应SIGKILL信号而退出

(变为TASK_ZOMBIE状态),并不会从TASK_INTERRUPTIBLE状态直接退出。


③TASK_UNINTERRUPTIBLE(不可中断):

处于等待中的进程,待资源满足时被唤醒,

但不可以由其它进程通过信号或中断唤醒

。由于不接受外来的任何信号,

因此无法用kill杀掉这些处于该状态的进程

。而

TASK_UNINTERRUPTIBLE状态存在的意义就在于



内核的某些处理流程是不能被打断的

。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程,于是原有的流程就被中断了,这可能使某些设备陷入不可控的状态。处于TASK_UNINTERRUPTIBLE状态一般总是非常短暂的,通过ps命令基本上不可能捕捉到。


④TASK_ZOMBIE(僵死):

表示进程已经结束了,

但是其父进程还没有调用wait4或waitpid()来释放进程描述符

。为了父进程能够获知它的消息,子进程的进程描述符仍然被保留着。一旦父进程调用了wait4(),进程描述符就会被释放。


⑤TASK_STOPPED(停止):

进程停止执行。当进程接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信号的时候。此外,

在调试期间接收到任何信号

,都会使进程进入这种状态。

当接收到SIGCONT信号,会重新回到TASK_RUNNABLE

二、查看进程状态

linux下命令:列出目前所有的正在内存中的进程


选项

含义
-a 显示终端上的所有进程,包括其他用户的进程
-u 显示进程的详细状态
-x 显示没有控制终端的进程
-j 列出与作业控制相关的信息
ps aux

ps的作用是显示当前运行的进程。

aux中:a显示用户使用的进程;

u

:使用以用户为主的格式输出进程信息;x显示机器的所有进程。

Q:作业控制是什么?

A:Shell分前后台来控制的不是进程而是作业或者进程组。一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell可以同时运行一个前台作业和任意多个后台作业,这称为作业控制。

进程显示样式:

stat中的参数意义如下:


参数

含义
D 不可中断 Uninterruptible(usually IO)
R 正在运行,或在队列中的进程
S(大写) 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程
< 高优先级
N 低优先级
s 包含子进程
+ 位于前台的进程组

三、孤儿进程

父进程运行结束,但是子进程还在运行的子进程就称为孤儿进程。

每当出现一个孤儿进程,内核就把孤儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。当孤儿进程结束声明周期时,init进程就会处理它的善后工作。所以孤儿进程没有什么危害。

四、僵尸进程

进程终止了,但是父进程还没回收子进程的资源,所以子进程的信息还保留在PCB中,所以还存在内核中,这样子进程就是僵尸进程。

这样就会导致一个问题,如果进程不调用wait() 或 waitpid() 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免。


Q:那遇到僵尸进程怎么处理呢?


A:

init进程回收法:

如果父进程先于子进程结束,那么子进程的父进程自动改为 init 进程。如果 init 的子进程结束,则 init 进程会自动回收其子进程的资源而不是让它变成僵尸进程。