进程的状态
- 指的是进程会有很多种运行状态,一会睡眠、一会暂停、一会又继续执行。如下图展示Linux进程从创建到被回收的全部状态,以及这些状态转换时的条件:
1、就绪态
- 当程序被用户执行/其父进程调用fork()成功,则一个进程就进入了就绪态
- 就绪态不代表正在运行,被CPU执行才称为运行态
- 就绪态实质就是一个在进程等待队列按优先排列的状态
2、运行态
- 进程从就绪态被sched(调度器)选中进入CPU并逐条执行他的指令
- 在运行态下时间片被耗光,则该进程会回到就绪态的进程等待队列中的末尾进行排队等待
如果进程被更高优先级进程抢占时间了,则该进程会退回到进程等待队列的头部继续等待
3、睡眠\挂起状态
- 在运行台态中,如果有某个资源暂时不能获取将会进入睡眠等待状态
- 用户使用sleep函数
- TASK_INTERRUPIBLE或则TASK_UNINTERRUPIBLE
- TASK_INTERRUPIBLE:浅睡眠,进程在该状态下可以被信号唤醒(比如等待某个文件的资源,当资源可获得时将会产生一个信号唤醒进程)
- TASK_UNINTERRUPIBLE:深度睡眠,与某些硬件相关,在睡眠过程中不会响应信号
4、暂停态
- 当进程收到STOPPED或则SIGTLSTP之一,则会从运行态变为暂停态
- 该状态下不参与系统得任何调度
- 需要等待到SIGCONT才会重新参与系统的进程调度
5、僵尸态
- 当进程退出时(主函数遇到return\调用exit函数等)情况下进程退出,会进入到僵尸状态
僵尸状态下,进程的尸体存放退出时的各种状态信息,比如:是否正常退出,退出值\异常退出、退出值\信号杀死、信号值等信息- 需要等待父进程查看子进程的尸体,获取解析其中的信息
- 当父进程成功获取子进程的退出信息后,则会把该僵尸态设置为退出状态(不占用内存空间)
6、死亡态
- 需要由父进程调用wait()\waitpid()来查看子进程的信息,从而把子进程设置为退出状态
- 如果父进程比子进程先结束,那么该子进程有祖父进程(IINIT)来接收并处理子进程的退出信息
总结:
1、就绪态:进程被创建或者父进程调用fork()成功后进入就绪态,表示进程准备好被调度执行,但尚未被分配CPU资源。
2、运行态:进程从就绪态被调度器选中进入CPU并逐条执行指令。在运行态下,如果时间片耗尽,则进程会回到就绪态的进程等待队列中排队等待。
3、睡眠/挂起状态:在运行态中,如果进程需要等待某个资源暂时不能获取,进程会进入睡眠等待状态。有两种睡眠状态:
TASK_INTERRUPIBLE(浅睡眠,可以被信号唤醒)
TASK_UNINTERRUPIBLE(深度睡眠,在睡眠过程中不响应信号)
4、暂停态:当进程收到STOPPED或SIGTSTP信号时,进程从运行态变为暂停态。在暂停态下,进程不参与系统调度,直到收到SIGCONT信号才重新参与调度。
5、僵尸态:当进程退出时,进程进入僵尸态。在僵尸态下,进程的退出状态信息被保存,等待父进程查看并处理。当父进程成功获取子进程的退出信息后,僵尸态被设置为退出状态。
6、死亡态:父进程通过调用wait()或waitpid()来获取子进程的信息,将子进程设置为死亡态。如果父进程先于子进程结束,子进程的退出信息将被其祖父进程(通常是init进程)接收并处理。