1.进程状态概念
进程状态是指操作系统对进程的运行状态进行的描述。
操作系统通过跟踪进程的状态来控制和管理它们的执行。这些状态的改变是由操作系统内核调度器决定的,根据进程需要,进程可以在这些状态之间进行切换。进程的状态取决于它需要等待的事件和资源,以及操作系统内核的调度决策。因此,不同的进程可能会处于不同的状态。
1.1 基本进程状态简单概念介绍
创建状态:当一个进程被创建时,它处于创建状态。在这个阶段,操作系统为进程分配必要的资源(将代码和数据拷贝到内存,创建PCB结构体等),并为其分配一个唯一的进程标识符(PID)。就绪状态:进程就绪状态是指进程已经满足了运行的条件,进程PCB被调度到CPU运行队列中,排队等待系统分配CPU资源来执行的状态。
运行状态:进程PCB被调度到CPU运行队列中且已被分配CPU资源,就叫做运行态。在这个阶段,进程的指令会被执行,它可以访问CPU和其他系统资源。只有运行状态下的进程才能占用CPU资源。
阻塞状态:当一个进程无法继续执行,因为它需要等待某些非CPU资源就绪时,它会进入阻塞状态。这些事件可能包括等待用户输入、等待磁盘I/O操作完成等。在阻塞状态下,进程会被调度到阻塞队列,不会占用CPU资源。只有当进程所等待的非CPU资源就绪后,进程才会从阻塞队列调度到运行队列(就绪状态)。
挂起状态 :当内存不足时,如果一个进程长时间不执行或者处于低优先级状态,操作系统可能会将其代码和数据置换出内存并存储到磁盘上的swap分区中。其PCB(进程控制块)仍然存在于进程表中。这是因为挂起状态只是进程的一种状态,表示进程暂时无法执行,但仍然需要保留进程的信息以便后续恢复执行。这样可以释放内存资源,给其他优先级较高的进程提供更多的执行机会。这些被置换到磁盘中的进程的状态就叫做挂起。
终止状态:当进程完成其任务或被操作系统终止时,它进入终止状态。在这个阶段,进程可以释放所有已分配资源,并从系统中移除。
2 运行状态 (R状态)
我们知道进程属性由PCB封装,它是一个结构体,当很多的进程要运行时,需要管理,设计者设计了一个队列,叫做运行队列。由这个运行队列管理进程。
正在处于运行队列中进程的状态我们称之为 运行态(R态)。
2.1 运行队列
Linux内核定义了一个list_head数据结构,字段head和prev分别表示通用的双向链表向前和向后的指针元素。
每个task_struct包含一个list_head类型的run_list字段。
如图所示:
运行时,进程PCB会进入运行队列,在cpu上运行,如图所示:
2.2 思考(时间片):
一个进程只要把自己PCB放到cpu上,是不是只要执行完毕,才会把自己放下来???
不是的!!!!
每个进程都会有一个叫做时间片的属性,时间片的作用是决定进程在cpu中待多长时间之后,自动结束进程。
所以,只要在运行队列上的进程,在一段时间内都会被执行,把大量的进程从cpu中切换,这就叫做并发执行。
3.阻塞状态
3.1相关知识
想要了解进程阻塞状态,先要了解一些关于硬件阻塞的相关知识:
操作系统和驱动程序它们对硬件进行管理,每个硬件都会有一个属于自己的结构描述,通过指针链接,操作系统通过链表(dev_list)达到对硬件设施的管理
硬件也和进程一样,被抽象陈成为一个个结构体,每一个硬件结构体都会有自己的属性,其中它们有一项共有属性:等待队列(wait_queue)
它们也会有自己的运行队列,将它们进行管理
3.2 进程运行的过程:
阻塞状态是建立在进程被调度执行的基础上,
在CPU执行一个进程时,都可能会或多或少的去访问系统的某些资源,比如:我们使用的scanf,在执行时需要调用键盘(本质就是从键盘中读取数据);
我们不输入(没有按下键盘),键盘的数据就是没有就绪(进程需要访问的数据没有就绪),此时进程无法继续执行,需要等待数据;
此时,这个进程PCB已经创建完成,但是它第一步进入的是设备(键盘),就只能进入键盘的等待队列中,当下一个需要读取读取键盘时,也会进入键盘的等待队列。
这个状态就叫做 等待状态!!
直到从键盘上读取后,该PCB才会由设备进入到cpu中,再从cpu进入到运行队列。(系统资源等待结束之后,操作系统会再次将等待队列中的PCB移入到运行队列当中,并把状态修改为运行状态,等待CPU的执行调度;)
进程PCB刚开始是进入设备中,再进入cpu中的!!
3.3 概念介绍
当进程正在等待某个硬件的资源时,把进程的PCB加入到硬件设备结构描述的等待队列当中,并把PBC的状态设置为阻塞状态;当PCB在这个等待队列中等待数据资源时,这个状态就叫做阻塞状态;
4.挂起状态
挂起状态是建立在阻塞状态的基础上的,当处于阻塞状态时,操作系统内部的内存严重不足!!
刚开始的PCB和数据代码都在内存中放着,但是当内存严重不足时,就会把代码和数据交换到磁盘中。
针对于这种情况,操作系统会将阻塞进程的代码和数据置换到外设,此时该进程的状态就被称为挂起状态;
阻塞进程的代码和数据一般会存放在磁盘的swap分区,当进程被操作系统调度时,被置换到外设的代码和数据又会重新加载到内存;
5 linux中的特别的进程状态
5.1 深度睡眠
情景解析:
当我们的一个进程需要往磁盘中写入1GB的数据时,但是磁盘正在被写入,并且内存中不断有进程进入。
操作系统看到后,这个进程一直在等待磁盘写入完毕的状态。
操作系统此时一般会杀掉该进程。
但是,也有些特殊的进程操作系统不能被杀掉,状态就叫做深度睡眠。
5.2 僵尸进程(“Z”)
僵尸进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵死进程。
字面意思,已经死掉的进程,理解过程中,还需添加一句——需要父进程关心(需要父进程手动关闭)!
进程退出的时候,如果父进程没有主动回收子进程信息,子进程会一直处于僵尸状态。进程的相关信息,尤其是task_struct不能被释放!
注意:用kill命令不能杀死僵尸进程,因为僵尸进程已经是退出的进程,只不过是资源未得到释放。
5.3 孤儿进程
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被 init 进程(进程号为1)所收养,并由 init 进程对它们完成状态收集工作。
当父进程被杀掉后,就会成为孤儿进程,此时孤儿进程会被操作系统接管。