Linux:深入理解进程的多种状态

目录

理解进程状态

运行状态(R)

阻塞状态(S) 

挂起状态(T)

僵尸状态(Z) 

孤儿进程

查看状态

进程优先级


理解进程状态

本篇在总结操作系统的进程的状态概念中,大多数情况下是根据的是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 */ // 比如调试程序打断点,在断点处停下来的状态
	"Z (zombie)",       /* 16 */
	"X (dead)",         /* 32 */
};
//解释各个状态的含义
R 运行状态(running):并不意味着进程一定在运行中,它表明进程要么在运行中,要么在运行队列里。
S 睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 interruptible sleep)。
D 磁盘休眠状态(disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待 IO 的结束。
T 停止状态(stopped):可以通过发送 SIGSTOP 信号给进程来停止进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
Z 僵尸状态(zombie)
X 死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

此图为状态的具体模型,操作系统描述的状态,放在任何操作系统中都是这样的:

  • 就绪 / 运行:R 状态
  • 阻塞:S / D / T 状态
  • 退出:Z / X 状态

其实理解状态很简单,状态就是PCB中的一个变量,例如在PCB中,可能会有一个变量定义为 int status,而在代码外面定义:

#define NEW 1
#define RUNNING 2
#define BLOCK 3

由此可以可以借助上面的宏定义,将状态进行修改:

pcb->status=NEW;
...

因此,所谓状态的变化过程,实际上就是修改整形变量的过程,通过修改整形变量就可以实现修改状态,那这个状态表示有什么用? 

if(pcb->status == NEW)
{
	// PCB进入运行队列
	...
}
else if(pcb->status == BLOCK)
{
	// PCB进入阻塞队列
	...
}

进程的状态,其实就是PCB的一个变量,因此状态只和PCB有关系,和代码数据无关 。

运行状态(R)

定义

  • 运行状态是指进程已获得CPU资源,并正在CPU上执行指令序列的状态。在单CPU系统中,任何时刻只能有一个进程处于运行状态;在多CPU系统中,则可以有多个进程同时处于运行状态,每个CPU核心上都可以运行一个进程。

特点

  • 占用CPU资源:进程在运行状态下能够使用CPU进行数据处理、逻辑运算等操作,按照程序代码的指令顺序依次执行,对数据进行加工和处理。
  • 进行资源访问:进程可以根据需要访问内存、I/O设备等系统资源,从内存中读取数据或将计算结果写入内存,与外部设备进行数据交互等。
  • 状态持续时间不确定:进程处于运行状态的时间取决于进程的任务复杂度、系统的调度策略以及其他进程的情况等。

状态转换

  • 就绪→运行:当处于就绪状态的进程被操作系统的调度程序选中,获得了CPU时间片,就会从就绪状态转换为运行状态。
  • 运行→阻塞:若进程在运行过程中需要等待某些事件发生,如I/O操作完成、等待获取信号量等,就会主动放弃CPU,进入阻塞状态。
  • 运行→就绪:在分时系统中,当进程的时间片用完,操作系统会暂停该进程的运行,将其放回就绪队列,使其进入就绪状态,等待下一次被调度执行。
  • 运行→终止:当进程完成了所有任务,执行到程序的结束指令,或者因为出现错误等异常情况被系统强制终止,就会从运行状态进入终止状态。

只要在运行队列中的进程都是运行状态。那么什么是运行队列呢?

通常来说,一个CPU可以负责管理一个运行队列,这里默认设备是一个单核的设备,那么CPU和内存和操作系统的管理方式如下所示:

每个CPU在系统层面上都会维护一个运行队列,对于上图来说,CPU就进行维护了一个runqueue队列,这个队列管理了一串PCB,而这当中的每一个PCB又进行管理了它们对应的可执行程序,此时,每一个可执行程序对应的PCB中的status数据都是NEW,代表着这些程序是正处于运行状态,是可以被随时调度的。那么:

一个进程是 R 状态,它一定在 CPU 上面运行吗?

不一定,进程在运行队列中也是 R 状态。如果一个进程想被 CPU 运行,就必须处在 R 状态才行。R 状态是:可运行状态。(准备好了,可以被调度。)

运行一下此代码:

#include<stdio.h>
#include<unistd.h>
int main()
{
    while(1)
    {
        printf("I'm running!\n");
        sleep(1);
    }
    return 0;
}

 

查看状态之后,为什么是S+状态(S)呢? 

  1. 因为该进程大部分时间都在休眠(sleep(1);)。
  2. 因为 printf 是往显示器上打印,涉及到 IO,所以效率比较低,该进程需要等待操作系统把数据刷新到显示器中。

所以,该进程绝大多数时间都在休眠,只有极少数的时间在运行,所以很难看到该进程处在 R 状态。当然写一个空死循环 while (1) {} 就可以看到R状态了。

阻塞状态(S) 

定义 

  • 阻塞状态是指进程因等待某种事件的发生而暂时无法继续执行的状态。处于阻塞状态的进程不能占用CPU资源,只有当所等待的事件完成或条件满足后,进程才会从阻塞状态转换为就绪状态,等待系统调度重新获得CPU资源后继续执行。

引发原因

  • I/O操作:进程需要读取或写入数据到外部设备,如硬盘、网络等,在数据传输完成前,进程会进入阻塞状态。
  • 等待信号量:进程在访问共享资源时,需要获取信号量来保证互斥访问。若信号量已被其他进程占用,该进程就会进入阻塞状态,等待信号量被释放。
  • 等待事件:进程可能在等待其他事件的发生,如等待特定的消息、等待定时器超时等,在事件发生前,进程会处于阻塞状态。

特点

  • 不占用CPU资源:阻塞状态下的进程不会获得CPU时间片,CPU会转而执行其他就绪状态的进程,以提高系统资源的利用率。
  • 无法主动推进:进程自身无法改变阻塞状态,只有当所等待的外部条件满足或事件发生时,才能由操作系统将其状态转换为就绪状态。
  • 可被信号唤醒:对于可中断的阻塞状态,进程可以被特定的信号唤醒,从而提前结束阻塞状态。

与其他状态的转换

  • 就绪→阻塞:就绪状态的进程在执行过程中,若遇到需要等待的事件,如发起I/O请求等,会转变为阻塞状态。
  • 阻塞→就绪:当进程所等待的事件完成或条件满足时,进程会从阻塞状态转换为就绪状态,进入就绪队列,等待系统调度。
  • 阻塞→终止:在某些特殊情况下,如等待的资源出现永久性错误或进程被强制终止等,阻塞状态的进程也可能直接进入终止状态。 

S:睡眠状态(sleeping)(浅度睡眠,大部分情况)

  • 表示进程虽然是一种休眠状态,但随时可以接受外部的信号,处理外部的请求,被唤醒。

D:磁盘睡眠状态(disk sleep)(深度睡眠

结合下面的举列子:

S:在程序运行时,若需要用户输入值而用户未输入,程序进程会从运行队列被移至等待队列,进入阻塞状态。当 Linux 系统运行压力过大时,系统会通过杀掉进程来节省资源。不过,杀掉进程代价较大,若进程涉及磁盘写入等关键操作,对用户而言损失惨。

D:为避免这种情况,Linux 系统专门设计了磁盘睡眠状态(disk sleep),也称为深度睡眠状态。此状态下的进程不会被随意终止,即便操作系统也无权对其进行操作。这一机制主要是为了保护与磁盘进行数据交互的进程,防止其被操作系统意外终止,确保数据的完整性和操作的稳定性。

     再来看以下例子:

    #include <stdio.h>
    
    int main()
    {
    	int a;
    	scanf("%d",&a);
    	printf("%d",a);
    	return 0;
    }
    

    当这个简单的输入输出程序运行时,它会被加载进内存,操作系统为其创建进程控制块(PCB)进行管理,此时程序转变为进程。若一直未输入值,导致键盘数据未就绪,进程所需访问资源缺失,进程代码无法向后执行,这种情况被称为阻塞状态

    操作系统作为系统资源的管理者,能及时感知进程进入阻塞状态,立即将其状态标记为 BLOCK。同时,为保证运行队列的高效性,操作系统会把该进程从运行队列移除,放入等待队列。那么什么是等待队列呢?

    等待队列是操作系统用于存放因资源未就绪而无法执行的进程的队列。进程进入阻塞状态,通常是因为代码中涉及对系统资源(如键盘、显示器、磁盘、网卡等硬件设备)的访问,而当前资源未就绪。例如用户不输入,scanf 无法获取所需数据,进程就不具备继续执行的条件。操作系统凭借对软硬件资源的底层管理能力,通过将阻塞进程移入等待队列,来维持系统的稳定运行和资源的合理分配,待资源就绪后,再将进程重新调度回运行队列 。

    而当阻塞队列中的进程的状态回到运行状态了,就可以将阻塞队列的进程再拿回到运行队列中即可

    因此,进程状态变化的本质?

    1. 更改PCBstatus的变量
    2. PCB连入不同的队列中

    不仅如此,操作系统会对所管理的硬件设备创建描述(dev 结构体),结构体中描述设备类型、硬件状态、指针等信息。对硬件设备构建属于它们自己的结构体,因此有了下面的演示:

    而由此可以得出一个结论:在操作系统中,会存在非常多的队列,运行队列,等待硬件的设备等待队列等,所有系统内的进程都是用双链表链接起来的。

    挂起状态(T)

    定义

    • 挂起状态是指进程暂时被操作系统从内存移到外存(如磁盘)中,或者虽然仍在内存但被标记为暂停执行的一种状态。处于挂起状态的进程不再参与CPU的调度,暂时停止运行,直到满足特定条件后才可能被唤醒并恢复执行。

    引入目的

    • 缓解内存压力:当系统内存资源紧张时,将一些暂时不运行的进程挂起,把它们占用的内存空间释放出来,以便给更需要内存的进程使用,提高内存的利用率。
    • 进程管理与控制:方便系统管理员或用户对进程进行管理和控制。例如,在调试程序时,可以将进程挂起,以便检查进程的状态、变量值等信息。

    分类

    • 主动挂起:进程通过自身调用挂起原语主动要求进入挂起状态,比如进程在执行过程中遇到需要等待长时间资源的情况,主动挂起自己,等待资源可用时再被唤醒。
    • 被动挂起:由操作系统或其他进程根据系统资源状况、调度策略等因素,强制将进程挂起。

    与其他状态的关系

    • 挂起状态可以与就绪、阻塞等状态相互转换。比如,一个就绪状态的进程可能因为系统内存不足被挂起成为挂起就绪状态;一个阻塞状态的进程也可能因为系统资源紧张等原因被挂起成为挂起阻塞状态。当满足特定条件,如内存空间足够、等待的资源可用等,挂起的进程又可以转换回就绪或阻塞状态,进而有可能再次进入运行状态。

    kill 命令:可以向目标进程发信号。 

    [ll@VM-0-12-centos 9]$ kill -l
     1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
     6) 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 号信号 SIGSTOP,可以让进程进入 T 停止状态。停止运行。

    • 我们给进程发 18 号信号 SIGCONT,可以让进程停止 T 停止状态。恢复运行。

      【画图理解】

      当进程处于阻塞状态时,表明其等待的资源尚未就绪,此时该进程无法被调度执行。不过,该进程仍驻留在内存中。若处于阻塞状态的进程数量较少,通常不会对系统造成明显影响。然而,一旦这类进程的数量达到一定程度,导致操作系统内的资源严重不足,系统就可能面临严峻的性能问题甚至崩溃。那么,在这种情况下,操作系统会采取什么措施来应对呢?

      当系统中阻塞进程数量过多,致使操作系统资源严重不足时,操作系统会选择将内存数据置换到外设,此操作针对所有阻塞进程,具体情况如下图所示:

      操作系统会将内存数据交换到哪里呢?答案是 swap 分区。当系统资源不足时,操作系统会把阻塞进程的数据转移到这个分区。当进程再次被调度时,存储在 swap 分区的代码和数据会被重新加载回内存,这就是一个换入和换出的过程。一旦信息被交换到磁盘,进程就进入了挂起状态。

      将阻塞进程的数据在内存和 swap 分区之间进行交换虽然是操作系统维持系统稳定运行的必要手段,但这种操作存在明显弊端。由于涉及数据的输入和输出,必然会导致系统效率降低。不过,若不进行这样的操作,整个系统极有可能面临崩溃的风险。所以,在实际开发中,为了在保证系统稳定运行的同时尽量减少效率损失,swap 分区的大小通常设置得与内存大小一致。  

      僵尸状态(Z) 

      定义

      • 当进程执行完任务或因错误等原因终止后,其进程描述符等信息仍保留在系统中,而相关的资源又未被完全释放,此时进程就处于僵尸状态,处于该状态的进程也被称为僵尸进程。

      产生机制

      • 进程终止流程:进程结束时会向父进程发送信号,内核将其状态设为僵尸状态,并保留其部分信息,如进程ID、退出状态等,等待父进程获取。
      • 父进程未响应:若父进程未调用相应函数获取子进程退出信息并释放资源,子进程就会一直保持僵尸状态。

      特点 

      • 资源占用:僵尸进程占用一定系统资源,主要是进程表项等内核数据结构空间,记录进程残留信息。不过,它不占用CPU时间片及内存等可执行程序的运行资源。
      • 不可运行:处于僵尸状态的进程无法再被调度执行,也不能通过常规方式恢复运行,它只是系统中的一个“残留”实体,等待被清理。
      • 状态标识:在Linux系统中,通过 ps 等命令查看进程状态时,僵尸进程的状态通常显示为“Z”或“Z+”。

      影响

      • 资源耗尽:大量僵尸进程会耗尽系统的进程表空间,使系统无法创建新进程,影响系统正常功能。
      • 性能下降:系统需维护这些僵尸进程的信息,增加了内核开销,可能导致系统性能下降,尤其在高并发场景下影响更明显。 
      • 僵尸进程是严重问题,若不解决会引发内存泄漏。
      • 子进程需维持退出状态告知父进程任务完成情况,父进程不读取,子进程就会一直处于 Z 状态。
      • 进程退出状态作为基本信息保存在 task_struct (PCB) 中,Z 状态不消失,PCB 就需持续维护。
      • 父进程创建大量子进程却不回收,会因 task_struct (PCB) 结构体占用内存空间导致内存资源浪费,即内存泄漏。

      解决方案

      • 进程等待(后面会讲到)

      【僵尸进程例子】

      #include <stdio.h>
      #include <stdlib.h>    // exit
      #include <sys/types.h> // getpid, getppid  
      #include <unistd.h>    // getpid, getppid, fork, sleep
       
      int main()
      {
          // 创建5个子进程
          for (int i = 0; i < 5; i++)
          {
              pid_t ret = fork();
              if (ret == 0)
              {
                  // child process
                  printf("child%d, pid:%u, ppid:%u\n", i, getpid(), getppid());
                  sleep(1);
                  exit(1); // 子进程退出
              }
          }
          getchar(); // getchar()目的是不让父进程退出,则无法回收子进程。
          return 0;
      }

       运行结果:成功创建了 5 个子进程。但程序会一直卡在这里,不会自己退出:

      值得注意的是,进程调度存在非确定性。以子进程打印顺序为例,其并不按照创建顺序(即编号 0 - 4)进行。这是因为操作系统调度进程执行的顺序并不固定,会受到多种因素影响,例如调度策略以及系统负载等。在实际例子中,可能出现 child4 输出首先出现,随后才是其他子进程输出的情况,这直观地展示了进程调度的这一特性。 

       

      while :; do ps ajx | head -1 && ps ajx | grep 可执行程序名称; sleep 1; echo "------"; done

      观察子进程状态的变化:5 个子进程退出后,因为父进程没有进行回收,都变成了僵尸状态。:

      【注意】

      在进程管理中,父进程的行为也十分关键。父进程通常会调用getchar()函数等待用户输入,这一操作能够防止父进程过早退出。然而,在大多数情况下,由于未调用wait/waitpid函数等待子进程结束,这意味着父进程不会立即回收已结束子进程的资源。

      需要强调的是,虽然父进程通过getchar()等待在一定程度上维持了进程的运行状态,但这并非处理僵尸进程的正确方式。僵尸进程是指已结束但未被父进程回收资源的子进程,它们会占用系统资源。在实际应用中,为了避免僵尸进程的产生,父进程应当使用wait/waitpid函数来等待子进程结束,并及时回收其资源,以此确保系统资源的高效利用和稳定运行。

      孤儿进程

      定义

      • 孤儿进程是指在其父进程先于自身结束或异常终止后,没有了父进程的进程。在这种情况下,孤儿进程会被系统的init进程(在Linux系统中通常是进程号为1的进程)收养,init进程会成为它的新父进程,负责对其进行管理和资源回收等操作。

      产生原因

      • 父进程正常结束:父进程完成任务后正常退出,而此时子进程还在运行,子进程就会成为孤儿进程。
      • 父进程异常终止:父进程可能由于程序错误、收到致命信号等原因突然终止,导致正在运行的子进程失去父进程。
      • 父进程被强制杀死:通过命令或其他方式强制杀死父进程,而子进程仍在运行,也会产生孤儿进程。

      特点 

      • 父进程变更:孤儿进程的父进程变为init进程或系统中类似功能的进程,由init进程来负责回收其资源等后续操作。
      • 继续运行:虽然失去了原来的父进程,但孤儿进程本身并不会立即终止,而是会继续运行,直到完成自身的任务或遇到其他导致其终止的情况。

      与僵尸进程的区别

      • 资源回收:孤儿进程有init进程负责回收资源,不会像僵尸进程那样因资源未被回收而一直占用系统资源。
      • 进程状态:孤儿进程是正常运行的进程,只是父进程发生了变更;而僵尸进程是已经结束运行但资源未被释放的进程,处于一种特殊的“死亡”状态。

      【孤儿进程例子】 

      #include <stdio.h>
      #include <stdlib.h>    // exit
      #include <sys/types.h> // getpid, getppid  
      #include <unistd.h>    // getpid, getppid, fork, sleep
       
      int main()
      {
          // 孤儿进程演示
          if (fork() > 0)
          {
              // father process
              sleep(3); // 父进程休眠3s后退出
              printf("father process exits!\n");
              exit(0);
          }
       
          // 子进程将执行这段代码
          while (1)
          {   
              printf("child process, pid: %u, ppid: %u\n", getpid(), getppid());
              sleep(1);
          }
          return 0;
      }

       运行结果:

      子进程状态变化:
       1号进程:

      当父进程结束时,会产生两个关键变化:一是父进程自身资源被回收;二是该父进程下的子进程,其进程父标识符(PPID)会变更为 1,同时这些子进程转为后台程序继续运行。这一现象引出了 “孤儿进程” 的概念:若子进程的父进程突然退出,子进程就会成为无人照料的 “孤儿”,这种情况下,子进程将被领养。而承担领养职责、PPID 为 1 的进程,正是 systemd initd 进程,它肩负起管理这些孤儿进程的重任,确保系统的稳定运行与资源的合理调度 。 

      查看状态

      进程状态查看命令:ps aux / ps ajx

      查看进程状态时,会看到 S+ 状态和 S 状态,那两个有什么区别吗?

      • S+ 状态:表示前台进程。(前台进程一旦运行,bash 就无法进行命令行解释,使用 Ctrl+C 可以终止前台进程)
      • S 状态:表示后台进程。(后台进程在运行时,bash 可以进行命令行解释,使用 Ctrl+C 无法终止后台进程,需要用到kill指令来杀死它,kill + pid / kill -9 + pid)

      在 Linux 系统里,存在 T 和 t 这两种进程状态,如今这两者的区别几乎可以忽略不计,它们都用于暂停进程。其中,tracing stop 状态更侧重于对进程的追踪,比如在 debug 模式下追踪断点时,就会涉及到这种状态。

      为什么会有这样的状态设置呢?当进程访问软件资源时,有时需要暂时停止对其访问,此时将进程设置为 STOP 状态就可以满足这一需求。

      在实际运用中,以 Linux 的调试工具 gdb 为例,其中的打断点操作十分常见。在 debug 程序时,打断点的本质是对程序进行追踪,一旦进程运行到断点处就会停止。这意味着,调试程序时进程处于运行状态,而打断点使其停下来的过程,实际上就是进程被终止(暂停)的过程。

      进程优先级

      1.核心概念

      定义

      • 优先级是进程获取系统资源(如CPU时间)的优先级顺序的量化指标,类似于现实生活中的“优先排队权”。

      作用:

      • 高优先级进程可优先获得CPU资源,提升关键任务的执行效率。
      • 支持将进程绑定到指定CPU(CPU亲和性),优化多核系统的性能。

      2.修改机制

      • 进程优先级由 pri(old)(原始优先级)和 nice 值共同决定。
      • 用户权限普通用户只能通过调整 nice 值间接影响优先级(范围受限),无法直接修改 pri(old)
      • 取值范围
        • 优先级最终值被限制在固定区间(如用户提到的 60-99,默认值为 80),确保系统调度的可控性。
        • (注:Linux实际实现中,nice 值的标准范围为 -20(最高)到 19(最低),优先级数值越低表示优先级越高)

      3.存在的必要性

      资源竞争

      • CPU在单时刻只能处理少量任务,而系统中存在大量进程竞争资源。
      • 优先级机制通过差异化调度策略,高效分配有限的CPU资源。

      实现方式

      • 优先级数值直接记录在进程的进程控制块(PCB)中,作为调度决策的核心依据。

      4.范围限制的原因

      避免进程饥饿

      • 若允许优先级无限高,低优先级进程可能长期无法获取资源,导致“饥饿”(Starvation)。
      • 区间限制确保所有进程均有机会被调度,维持系统公平性。

      5.相关边缘概念

      • 竞争性:多个进程争夺同一CPU资源,优先级机制是解决资源竞争的调度策略。
      • 独立性:进程间资源隔离,各自独立运行,互不干扰(如内存、文件描述符独立分配)。
      • 并行(Parallelism):多个CPU核心同时执行不同任务,实现真正的多任务同时处理(依赖多核硬件)。
      • 并发(Concurrency):单个CPU通过快速切换进程上下文,在宏观上“同时”推进多个任务(微观上交替执行)。

      【总结】

      优先级机制是操作系统调度算法的核心设计之一,通过合理分配CPU资源,平衡效率与公平性。理解其实现细节(如 nice 值、优先级区间限制)及关联概念(竞争性、并发/并行),有助于优化程序性能及系统调优。

      在 Linux 或者 Unix 系统中,使用命令 ps -al 查看当前系统进程的信息: 

      在 Linux 中,标识一个用户,不是通过用户名来标识的,而是通过用户的 UID。计算机比较善于处理数据,UID 是给计算机看的,UID 对应的用户名是方便给人看的。比如 QQ 可以随意更改昵称,那就说明昵称不是唯一标识这个 QQ 用户的,而是通过 QQ 号。

      • UID:代表执行者的 ID,通过命令 ll -n 可以查看。 
      • PID:代表这个进程的代号。
      • PPID:代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号。
      • PRI:表示这个进程可被执行的优先级。
        • 其值越小,优先级越高,越早被执行。
        • 其值越大,优先级越低,越晚被执行。
      • NI:nice 值,表示进程可被执行的优先级的修正数值:[-20, 19],一共 40 个级别。
      • 进程新的优先级:PRI(new) = PRI(old, 默认都是 80) + nice

      执行 top 命令后,按 r 键,输入进程的 PID,输入 nice 值。

      每次输入 nice 值调整进程优先级,都是默认从 PRI = 80 开始调整的。
      输入的 nice 值如果超过 [-20, 19] 这个范围,默认是按照最左/最右范围来取的。 

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

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

      余额充值