进程状态的概念
顾名思义,进程状态就是进程目前所处的状态。
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
一般我们把进程分为六种状态:
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
(interruptible sleep))。- D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
- Z僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。
不过,详细介绍这6种状态之前,我们还需要了解阻塞和挂起这两个概念。
阻塞
所谓组设,就是指进程因为等待某种条件就绪,而导致一种不推进的状态。
我们都知道,进程是先描述再组织的。对于我们调用某一项资源也是这样。
举个例子:
OS是款搞管理的软件,所以它能够管理网卡、屏幕、键盘等硬件资源,但是OS并不是直接管理这些硬件的,OS会先描述出每个硬件基本信息,并且将这些基本信息放入一个结构体中,然后再利用某种数据结构将这些结构体再组织起来,这样OS就可以很好地管理硬件资源了。
管理起了硬件资源后,那么我们如何去使用这些硬件资源呢?
实际上在存储硬件信息的结构体中,还有一个队列,这个队列是专门用来记录需要申请该硬件资源的进程的pcb。当我们的某一个进程需要调用某个硬件资源的时候,就会将该进程的pcb放入该硬件资源调用的这个队列中。而此时进程不会进行下去,所以该进程的pcb也就移出了cpu队列。
当然,整个内存中可能有许多进程需要调用这一个硬盘资源。但这个硬盘资源又不可能被多个进程同时调用。所以,当一个进程在调用该硬盘资源的时候,其他需要调用该硬盘资源的进程就会在申请该硬盘资源的队列中进行等待。此时进程并没有被cpu调度,所有在等待调用资源的进程的行为就是阻塞。而当这个等待的进程等到需要的资源时,该进程的pcb就会加载进cpu队列中,等待cpu的处理。
挂起
挂起状态可以说是一个特殊的阻塞状态。
挂起进程在操作系统中可以定义为暂时被淘汰出内存的进程,机器的资源是有限的,在资源不足的情况下,操作系统对在内存中的程序进行合理的安排,其中有的进程被暂时调离出内存,当条件允许的时候,会被操作系统再次调回内存,重新进入等待被执行的状态即就绪态。
但是OS并不会销毁转移进磁盘的进程的pcb,所以OS还是能管理到该进程的。此时进程处于的这种状态就叫做挂起状态。当该进程分配到对应资源时,OS又会将该进程的代码数据从外存调回内存。
运行状态
对于处于运行状态的程序来说,并不代表着进程一定处在运行中,它表明进程要么是在运行中要么在运行队列中。
不过一个程序处于R状态的时间非常短暂。因为cpu的运行速度是非常快的,往往一个进程一瞬间就不再是R状态了。大部分时候,进程都处于等待资源调用的状态即S状态。
睡眠状态
当进程为了等待某种资源,而处于等待队列当中的状态称为睡眠状态。
而我们上面所讲解的阻塞状态也属于睡眠状态,被称为浅睡眠状态或可中断睡眠。即我们可以kill掉处于该状态的程序。
以上面程序为例,按理说程序是一直printf,是一直在执行。所以这个程序会一直处于R状态么?
不难发现test程序是一处于S状态的,这是为什么呢?
因为cpu在处理printf语句时,会让该进程调用屏幕资源,将“******”打印到屏幕。此时,该进程就会离开cpu队列,去屏幕资源的等待队列中等待屏幕资源的分配,所以我们看到的是S状态。因为cpu运行很快,