【Linux】进程状态优先级
7.进程状态优先级
文章目录
- 7.进程状态优先级
- 一、进程的状态
- 补充
- 二、Linux下进程的状态
- 进程状态源代码
- sleeping与Disk sleep的区别
- stopped和tracing stop
- X 状态和 Z 状态
- 进程退出信息的获取
- 三、总结一下
一、进程的状态
-
这是任何一本操作系统教材都会展示的进程状态图。不管以前是否见过,在操作系统中,进程从创建到就绪,由系统调度运行,运行完终止销毁。运行过程中,若发生某些事情需要等待,则阻塞。阻塞完毕后,完成相关操作后再进入就绪状态,这个过程循环进行,称为进程状态。
-
在操作系统中,状态的概念必须遵循一个原则,即所学理论必须在多种操作系统中通用,如Linux、Windows和macOS。操作系统学科的知识需高于具体操作系统,以保证其兼容性。
我们先以比较简单的思路来理解这一个进程状态图:
先不管挂起状态,只看新建、就绪、运行、阻塞、退出。
对于一个进程,当其刚开始被加载到内存时,称为新建状态。创建完成后,进程进入就绪状态,表示已准备好接受调度。进程处于就绪状态时,意味着它已准备好,可以随时被操作系统调度。当CPU有时间时,会将该进程放到CPU上运行,此时进程处于运行状态。*运行状态存在些许争议,后续将统一概念。*在运行本质上,即进程在CPU上被调度和执行时。
因某些IO事件发生,比如用C语言写代码,其中涉及scarf函数,当CPU执行到scarf时,若用户未在键盘输入则scarf这行代码会卡在代码中,即执行停滞。此时,我们称之为IO事件,即等待用户从键盘输入,若用户未输入,则一直停滞。但不能让CPU一直停滞,所以一旦向scarf函数传入数据但用户未在键盘输入时,操作系统会将此运行进程放入队列区,使其进入阻塞状态。当用户按下键盘,有数据输入时,进程会从阻塞状态切换回就绪状态。
补充
-
并行与并发
并发:CPU执行进程代码,不是把进程代码执行完毕,才开始执行下一个,而是给每一个进程预分配一个时间片,基于时间片,进行调度轮转(单CPU下),
也就是说:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
并行:多个进程在多个CPU下分别,同时进行运行,这称之为并行 -
时间片
Linux/windows民用级别的操作系统,分时操作系统,时间片是分时操作系统分配给每个正在运行的进程在微观上的一段CPU时间-
时间片是操作系统在进程调度中使用的概念,用于实现多任务处理。
-
在单CPU系统中,通过时间片轮转,多个进程看似同时运行,但实际上是轮流使用CPU
-
当一个进程的时间片用完,它会被放回就绪队列的末尾,等待下一次调度
-
所有进程都有机会得到相同的CPU时间,避免某些进程长时间得不到执行,调度任务追求公平
-
-
进程具有独立性
-
之前提到过但是没有做笔记:进程 = PCB(进程控制块) + 程序代码和数据
-
等待的本质:链入目标外部设备,CPU不调度!下面是对这一理解的说明:
-
增加概念:运行队列(Run Queue)
每个CPU内核维护一个运行队列(数据结构
struct run_queue
),用于存放所有可被调度的进程PCB。进程被加入运行队列即处于运行状态(或称就绪状态),等待CPU时间片轮转调度。调度算法(如FIFO)通过队列的入队、出队操作管理进程执行顺序。 -
对阻塞状态的理解:
当进程访问外设(如键盘、磁盘)且设备未就绪时(如键盘无输入),操作系统会将进程PCB从运行队列移至设备等待队列,进入阻塞状态。阻塞的本质是进程等待硬件资源,此时CPU不会调度该进程,代码执行暂停。设备就绪后(如用户输入完成),操作系统将进程PCB重新加入运行队列,恢复调度。
-
操作系统的硬件管理机制
先描述后组织:操作系统通过结构体(如
struct device
)描述硬件属性(状态、类型等),并以链表组织所有硬件设备。每个硬件设备维护一个等待队列,存储因等待该设备而阻塞的进程PCB。硬件状态变化(如键盘输入完成)由操作系统通过驱动感知,触发进程状态迁移。 -
进程状态转换的本质
运行状态:PCB在CPU的运行队列中,等待CPU资源。阻塞状态:PCB在外设的等待队列中,等待硬件资源。状态转换即PCB在不同队列间的移动,由操作系统通过数据结构操作实现。
-
比如卡顿现象的根源
进程过多导致CPU调度周期延长,或外设竞争激烈,进程在队列中等待时间超出用户感知阈值。
表现为上层应用响应延迟,本质是操作系统调度和硬件资源分配的效率问题
-
结论
- 阻塞的本质:进程因等待外设资源被移出运行队列,加入设备等待队列。
- 运行的本质:进程在运行队列中等待CPU调度。
- 操作系统通过队列管理(运行队列、设备等待队列)实现进程状态切换和资源分配,核心是数据结构的增删查改操作。
-
-
挂起状态
-
背景:一种极端情况,比如内存资源严重不足时。
-
现假设内存资源已严重不足,若一个进程正在读取代码和数据,或读取数据但因键盘数据未就绪,操作系统会将该进程列入设备等待队列,开始等待。
-
在等待期间,该进程不会被调度。但需注意,**该进程的PCB是数据结构对象,占用一定内存;同时,该程序对应的代码和数据也占用内存。**然而,该进程处于阻塞状态,不会被调度,代码和数据仍占用内存,但实际上这部分内存在系统层面上被白白浪费,因为操作系统不会调度该进程,直至真正需要时。当操作系统需要访问和执行该进程的代码和数据时,却未调度该进程,导致该进程处于等待状态。
-
此时内存资源严重不足,为保证整个操作系统的安全,操作系统自身也需要申请内存,包括新加载进程时在系统层面上重新申请taskstruct的空间。若操作系统无法申请到内存,将直接报错。
-
若系统内存严重不足,操作系统会采取相应措施。若当前进程处于阻塞状态,其代码和数据占用内存但无实际意义,操作系统会将该进程的部分代码和数据换出至磁盘。等待约五秒钟后,若用户按下键盘数据,进程被操作系统识别为数据就绪,操作系统会将该进程重新放入运行队列,以便在CPU上运行。
-
此时,若操作系统直接将该进程放入运行队列,而其代码和数据已被换出至磁盘,则CPU执行时将缺少代码和数据,导致问题。此时,操作系统在将进程换入运行队列前,除将阻塞状态改为运行状态并将PCB列入运行队列外,还需将进程在磁盘中保存的代码数据换入内存,这称为换入。通过换出和换入,操作系统可将暂时不用的代码和数据临时保存至磁盘。磁盘中专门用于换入换出的系统级别分区称为swap分区或交换分区。此时被换出的进程处于严格意义上的阻塞挂起状态,即不仅被阻塞,还被挂起。
-
所以swap分区做挂起的本质是用时间换空间
-
-
拓展点:一般在云服务器上,这个功能会被禁掉。因为云服务器那些互联网公司相比这一点点内存资源,更加倾向的是要时间。如果你允许操作系统做换入换出,如果操作系统压力比较大,此时操作系统高度频繁地进行换入换出,换入换出的本质是在做io,也就是我们和外设进行交互。我们曾经讲过冯诺依曼体系,而io就意味着会非常慢。在我们平常老百姓用起来,等一等就完了。但是对于那些互联网公司,它不允许或者可能会导致机器变慢。
-
阻塞和进程切换这两个概念虽然不是高频面试点,但我们学习肯定是为了笔试面试做准备的。有些必要的知识,比如阻塞、挂起等概念,如果不理解,后面面试中的问题就很难理解。所以必要的知识储备是要有的。
二、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 */
}
解释:
- R 运⾏状态(running): 并不意味着进程⼀定在运⾏中,它表明进程要么是在运⾏中要么在运⾏队列⾥。
- S 睡眠状态(sleeping): 意味着进程在等待事件完成(这⾥的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
- D 磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T 停⽌状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停⽌(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运⾏。
- X 死亡状态(dead):这个状态只是⼀个返回状态,你不会在任务列表⾥看到这个状态。
举例:
[user@hcss-ecs-b735 ~]$ ps ajx | head -1; ps ajx | grep codePPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
27159 27986 27986 27159 pts/1 27986 S+ 1000 0:00 ./code
27661 27990 27989 27661 pts/2 27989 S+ 1001 0:00 grep --color=auto code
代码中的STAT就是这个进程当前的状态,+
表示任务在前台运行,S
根据前面的源代码可知目前这个进程处于浅睡眠状态
sleeping与Disk sleep的区别
上面是其中一种状态,d状态也是一种休眠,是阻塞等待状态的一种,只不过d状态在同学们以前的学习生涯里可能未见过,在未来职业生命周期里同样也很少见。但d状态确实客观存在,我们把它叫做不可中断睡眠,也就是深度睡眠。
- 独占磁盘I/O操作期间进入
- 拒绝响应任何信号(包括kill -9)
- 保证关键数据完整性
90%的健康操作系统中,D状态很难出现,它是瞬时状态,与其他状态一样,很难被检测到。一旦在机器或公司未来查到D状态,一般而言,出现D状态通常意味着磁盘或整个系统已接近故障。若系统中查到进程处于D状态,则表明磁盘已出现问题,可能是磁盘老化、空间严重不足等。此时磁盘会不断进行碎片数据合并以节省空间,系统离故障不远。若系统长时间出现D状态且无法恢复,则系统可能直接崩溃。
stopped和tracing stop
我们先来认识一个命令:kill;kill
命令用于向进程发送信号,通常是用来终止进程。默认情况下,kill
发送的是 TERM
信号(终止信号),但也可以通过选项指定其他信号。
[lisihan@hcss-ecs-b735 ~]$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
要想暂停和回复进程我们可以用19和18两个信号
kill -19 <PID> # 暂停进程(SIGSTOP)
kill -18 <PID> # 恢复运行(SIGCONT)
举例:
-
暂停状态的出现有两种情况:它做了非法,但是不致命的操作,此时被操作系统直接暂停了。第二种情况它主要是不允许你去做某件事情。
-
当我们从新把进程恢复之后,我们如果用
ctrl c
无法结束进程,并且当我们再去查进程状态的时候,它的状态是s,但没有不见后面的加号。==因为你刚刚把这个进程暂停了一下,又把它重新启动,像这种暂停再重新启动,这个进程自动变到后台去运行了。==所以无法使用ctrl c来终止它。此时这种情况只能使用kill -9 <pid>
来结束进程。后面带着加号ctrl c, 能终止这种进程,叫前台进程。当前台进程运行时我们在命令行输入任何命令都没有作用,但如果程序在后台就可以使用命令行指令 -
如果想让这个进程跑到后端,我们需要在启动进程的时候在后面加上
&
,注意要用空格隔开
[lisihan@hcss-ecs-b735 lession11]$ ./code &
[1] 32477
[lisihan@hcss-ecs-b735 lession11]$ hello world, cnt : 0
hello world, cnt : 1
hello world, cnt : 2
hello world, cnt : 3
hello world, cnt : 4
hello world, cnt : 5
hello world, cnt : 6
hello world, cnt : 7
hello world, cnt : 8
hello world, cnt : 9
hello world, cnt : 10
ll
total 20
-rwxrwxr-x 1 lisihan lisihan 9456 May 27 13:59 code
-rw-rw-r-- 1 lisihan lisihan 210 May 27 13:59 code.c
-rw-rw-r-- 1 lisihan lisihan 61 May 26 17:04 Makefile
[lisihan@hcss-ecs-b735 lession11]$ hello world, cnt : 11
这样创建的进程直接就是后台进程,之后会显示他的任务编号以及对应的pid[1] 32477
。把这个任务启动起来之后,系统自动去自动完成,用户继续进行命令行操作。
还有一个状态叫做t
追踪暂停,一般是启用调试工具对代码进行调试时会出现的状态,如用gbd调试代码
所以为什么遇到断点进程会暂停呢?暂停状态叫做当一个进程需要被追踪时,该进程那么可以被我们的调数器设置为小t状态来进行追踪。
X 状态和 Z 状态
-
X 状态:死亡状态,进程完全退出,操作系统回收其资源。
-
Z 状态(Zombie 僵尸状态):
进程运行完毕,但父进程尚未读取其退出信息(如退出码),所以暂不被回收;保留退出信息供父进程查询;父进程读取退出信息后,进程才从 Z 状态转为 X 状态,彻底退出。
进程退出信息的获取
- 使用
$?
获取最近一个命令的退出码; - 主函数
main()
返回值即为退出码,返回0
表示成功,非 0 表示失败;操作系统和父进程可以通过这个退出码判断任务是否顺利完成。
三、总结一下
本文阐述了进程状态与优先级的核心概念,重点围绕进程的生命周期状态转换及其在Linux系统中的具体实现展开。进程从创建到终止,历经就绪、运行、阻塞等基本状态,其本质是操作系统通过运行队列与设备等待队列的动态管理实现资源调度。阻塞状态反映了进程因等待外设资源而暂停执行,而挂起状态则是内存不足时通过换入换出机制以时间换取空间的策略。在Linux中,进程状态进一步细化为R(运行/就绪)、S(可中断睡眠)、D(不可中断磁盘休眠)、T(暂停)、Z(僵尸)等状态,其中D状态预示系统潜在故障,Z状态需父进程主动回收资源以避免内存泄漏。通过kill命令可操控进程状态,如暂停与恢复运行,而后台进程的管理则通过&
符号实现。希望对各位有帮助。