【Linux】进程状态和进程优先级

本文详细介绍了进程的不同状态,包括运行、阻塞、挂起等,并特别讨论了Linux中的进程状态,如R(运行)、S(睡眠)、D(磁盘休眠)、T(停止)和Z(僵尸)。此外,还阐述了僵尸进程和孤儿进程的概念及其对系统的影响,以及进程的优先级和nice值如何影响进程执行的顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1. 进程状态

为了更深入地了解进程,我们需要知道进程的不同状态。

不同的操作系统,对于进程状态有着不同的说法,如:运行、阻塞、挂起、新建、就绪、等待、死亡等。进程的多种状态,本质上是为了满足不同的应用场景。这里我们了解几种普遍的状态:

  • 运行状态
    每个CPU都只有一个运行队列,进程的执行需要入队,而让进程入队的本质是将该进程的task_struct结构体对象放入运行队列中。在CPU的运行队列中的进程,其状态称为运行状态。

在这里插入图片描述

  • 阻塞状态
    进程在运行过程中会占用CPU和其他硬件(如外设)资源,CPU与其他硬件相比,二者处理进程请求的速度相差甚远,如果等待其他硬件处理完毕,CPU再执行下一个进程,那么系统的整体速度会大幅降低;
    所以:当CPU发现运行队列中进程需要占用其他硬件资源时,会将该进程移至被占用硬件的等待队列(wait_queue)中进行排队,这种进程的状态称为阻塞状态。

在这里插入图片描述

  • 挂起状态
    我们知道进程 = 进程的数据结构 + 磁盘上的代码和数据,而进程执行时会将磁盘上对应的代码和数据加载到内存;硬件响应速度慢,当有大量进程访问硬件时会产生较多的阻塞进程,这些进程的代码和数据在短期内不会被使用,如果一直在内存会占用很多内存资源。此时操作系统会将其代码和数据移至磁盘,仅保留PCB,以节省空间,这种进程的状态称为挂起状态。
    在这里插入图片描述

挂起状态也可以叫做阻塞挂起状态,所以阻塞状态不一定是挂起状态,挂起状态一定是阻塞状态。

总结:

  1. 状态是进程的内部属性,具体地说,状态是PCB中的一个整数值。
  2. 进程的状态,本质是进程在不同的队列中,等待某种资源
  3. 进程的PCB在运行队列(run_queue)中,其状态就是运行状态(R),不是进程正在运行才是运行状态
  4. 进程既占用CPU资源又占用其他硬件(如外设)资源

2. Linux的进程状态

在Linux内核里,进程有时候也叫做任务(task)。

下面是状态在kernel源代码里的定义:

在这里插入图片描述

  • R运行状态(running):
    进程的状态为R,并不意味着进程一定在运行中,它表明进程要么是在运行中要么是在运行队列里。

test.c

#include <stdio.h>
int main()                                                                                        
{
  while (1);
  return 0;
}

+表示前台进程,没有+表示后台进程。前台进程运行时,无法输入指令,Ctrl + C可以终止进程;后台进程运行时,可以输入指令但Ctrl + C不能终止进程,可以使用kill -9 PID杀死进程。

在这里插入图片描述

  • S睡眠状态(sleeping):
    意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))

mytest.c

#include <stdio.h>                                                                                
int main()
{
  int cnt = 0;
  while (1)
  {
    printf("%d\n",cnt++);
  }
  return 0;
}

在这里插入图片描述

S状态是浅度睡眠状态,是阻塞状态的一种,是可以被终止的进程状态。虽然数字一直在打印,但大部分时间在等显示器IO就绪,只有小部分时间在执行打印代码。所以查询该进程的状态大概率是S状态,上图碰巧查询到了R状态。

  • D磁盘休眠状态(Disk sleep):
    有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
    D状态一般在高IO的情况下才会发生,此状态下的进程处于深度睡眠,无法被杀死,只有通过断电或等待进程自己”醒来“的方式才能中断D状态。
  • T停止状态(stopped):
    T状态是阻塞状态的一种。可以通过发送 SIGSTOP 信号kill -19 PID给进程来停止进程。这个被暂停的进程可 以通过发送 SIGCONT 信号kill -18 PID让进程继续运行。

在这里插入图片描述

  • X死亡状态(dead):
    这个状态只是一个返回状态,无法在任务列表里看到这个状态。

3. 僵尸进程

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。

僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
 
int main()  
{  
 pid_t id = fork();  
 if (id == 0)  
 {  
   while (1)  
   {  
     printf("子进程:PID: %d PPID: %d\n", getpid(), getppid());  
     sleep(1);  
     exit(1);                                                                                    
   }  
 }  
 else if (id > 0)  
 {  
   while (1)  
   {  
     printf("父进程:PID: %d PPID: %d\n", getpid(), getppid());  
     sleep(1);  
   }  
 }  
 else {  
   perror("fork失败");  
   exit(-1);  
 }  
 return 0;  
}

下面这行脚本可以实时监控进程:

while :; do ps ajx | head -1 && ps ajx | grep mytest | grep -v grep; sleep 1;done

在这里插入图片描述

  • 僵尸进程危害
    • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程)你交给我的任务,我办的怎么样了。如果父进程一直不读取,那子进程就一直处于Z状态
    • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护
    • 一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,类比C中定义一个结构体变量,是要在内存的某个位置开辟空间
    • 僵尸进程会导致内存泄漏

4. 孤儿进程

父进程先退出,子进程就称为孤儿进程

那么父进程提前退出,子进程后退出,进入Z状态之后,该如何处理呢?

此时孤儿进程会被1号init进程领养,子进程的资源由init进程回收

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
 
int main()  
{  
 pid_t id = fork();  
 if (id == 0)  
 {  
   while (1)  
   {  
     printf("子进程:PID: %d PPID: %d\n", getpid(), getppid());  
     sleep(1);                                                                                      
   }  
 }  
 else if (id > 0)  
 {  
   while (1)  
   {  
     printf("父进程:PID: %d PPID: %d\n", getpid(), getppid());  
     sleep(1); 
     exit(1); 
   }  
 }  
 else {  
   perror("fork失败");  
   exit(-1);  
 }  
 return 0;  
}

在这里插入图片描述


5. 进程优先级

  • 基本概念

    1. cpu资源分配的先后顺序,就是指进程的优先权(priority)
    2. 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
  • 查看进程优先级
    在linux或者unix系统中,用ps -al命令则会类似输出以下几个内容
    在这里插入图片描述

几个重要信息:
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI(默认80) :代表这个进程可被执行的优先级,其值越小越早被执行
NI (默认0):代表这个进程的nice值

  • PRI和NI

PRI是进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高

NI就是nice值,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,加入nice值后,会使得PRI变为:新的PRI = 默认PRI + nice

这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。 在Linux下,调整进程优先级,就是调整进程nice值。 nice的取值范围是-20至19,一共40个级别

  • 修改nice值

执行sudo top进入top后按“r” -> 输入进程PID -> 输入nice值

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二木 同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值