¿Qué debo hacer si hay una gran cantidad de procesos ininterrumpibles y procesos zombies en el sistema?

estado del proceso

A través del comando superior, podemos ver el estado del proceso (columna S)

top


top - 19:27:57 up 365 days, 25 min,  0 users,  load average: 0.06, 0.05, 0.01
Tasks: 134 total,   1 running,  90 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.5 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3514764 total,   137136 free,  1193824 used,  2183804 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1965284 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                    
11399 root      20   0 1114904 150016  19564 S   1.0  4.3 537:19.31 YDService                                  
 9951 ubuntu    20   0 1142180 261916  36424 S   0.7  7.5   0:44.05 node                                       
15178 ubuntu    20   0   41144   3700   3032 R   0.3  0.1   0:00.06 top                                        
30256 root      20   0   64552  11232   3632 S   0.3  0.3  41:52.93 barad_agent                                
30257 root      20   0  588648  20356   4840 S   0.3  0.6 316:58.21 barad_agent                                
    1 root      20   0  225544   7596   4920 S   0.0  0.2  19:35.77 systemd                                    
    2 root      20   0       0      0      0 S   0.0  0.0   0:13.93 kthreadd                                   
    4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H

El estado del proceso es el siguiente:

  • R es la abreviatura de Running o Runnable, lo que significa que el proceso se está ejecutando o esperando para ejecutarse en la cola lista de la CPU.

  • D es la abreviatura de Disk Sleep, es decir, Uninterruptible Sleep (Sueño ininterrumpido), lo que generalmente significa que el proceso está interactuando con el hardware, y no se permite que el proceso de interacción sea interrumpido por otros procesos o interrupciones.

  • Z es la abreviatura de Zombie, es decir, el estado zombie. El proceso en realidad ha terminado, pero el proceso padre no ha reclamado sus recursos (como el descriptor de proceso, PID, etc.).

  • S es la abreviatura de Interruptible Sleep, es decir, estado de suspensión interrumpible, lo que significa que el sistema suspende el proceso porque está esperando un evento. Cuando ocurre el evento que el proceso está esperando, se despierta y entra en el estado R.

  • I es la abreviatura de Idle, es decir, el estado inactivo, que se utiliza en subprocesos del núcleo que no pueden interrumpir el sueño. Como se mencionó anteriormente, el proceso ininterrumpido causado por la interacción del hardware está representado por D, pero para algunos subprocesos del kernel, es posible que en realidad no tengan ninguna carga, y se usa Idle para distinguir esta situación. Tenga en cuenta que los procesos en el estado D aumentarán el promedio de carga, mientras que los procesos en el estado I no lo harán.

  • T o t, que es la abreviatura de Stopped or Traced, significa que el proceso está en estado suspendido o rastreado. Envíe una señal SIGSTOP a un proceso y se suspenderá (Detenido) en respuesta a esta señal; envíele una señal SIGCONT y el proceso reanudará su ejecución. Y cuando usa un depurador (como gdb) para depurar un proceso, después de usar un punto de interrupción para interrumpir el proceso, el proceso se convertirá en un estado de seguimiento, que en realidad es un estado de pausa especial, pero puede usar el depurador para realizar un seguimiento. controlar la operación del proceso según sea necesario.

  • X, abreviatura de Dead, significa que el proceso está muerto, por lo que no lo verá en los comandos top o ps.

estado ininterrumpido

Primero mire el estado ininterrumpible, que en realidad es para garantizar que los datos del proceso sean consistentes con el estado del hardware y, en circunstancias normales, el estado ininterrumpible finalizará en poco tiempo. Por lo tanto, generalmente podemos ignorar el proceso de estado ininterrumpible a corto plazo.

但如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,你就得注意下,系统是不是出现了 I/O 等性能问题。

僵尸进程

僵尸进程,这是多进程应用很容易碰到的问题。正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源;而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。

如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。

通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。

大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。

iowait 分析

我们先用dstat分析一下数据

# 间隔1秒输出10组数据

dstat 1 10

You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw 
  0   0  99   0   0|3880B   47k|   0     0 |   0     0 | 379  1240 
  1   2  98   0   0|   0     0 |1332B 2039B|   0     0 | 884  1683 
  2   3  95   0   0|   0     0 |1158B 3065B|   0     0 |1066  2113 
  2   1  96   1   0|   0   384k|2548B 3323B|   0     0 |1018  1991 
  0   0 100   0   0|   0     0 | 364B  380B|   0     0 | 616  1166 
  1   0  99   0   0|   0     0 | 986B 1016B|   0     0 | 739  1432 
  1   1  98   0   0|   0     0 |1304B 5305B|   0     0 | 775  1659 
  1   1  98   0   0|   0     0 |1950B  909B|   0     0 | 764  1450 
  1   1  98   0   0|   0    68k|2898B 4832B|   0     0 | 799  1423 
  1   1  98   0   0|   0     0 | 856B 1088B|   0     0 | 667  1382

pidstat 查看IO

# -d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 10 组数据

pidstat -d -p 9951 1 10


Linux 4.15.0-180-generic (VM-0-11-ubuntu)       08/04/2023      _x86_64_        (2 CPU)

07:40:23 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
07:40:24 PM   500      9951      0.00      0.00      0.00       0  node
07:40:25 PM   500      9951      0.00      0.00      0.00       0  node
07:40:26 PM   500      9951      0.00      0.00      0.00       0  node
07:40:27 PM   500      9951      0.00      0.00      0.00       0  node
07:40:28 PM   500      9951      0.00      0.00      0.00       0  node
07:40:29 PM   500      9951      0.00      0.00      0.00       0  node
07:40:30 PM   500      9951      0.00      0.00      0.00       0  node
07:40:31 PM   500      9951      0.00      0.00      0.00       0  node
07:40:32 PM   500      9951      0.00      0.00      0.00       0  node
07:40:33 PM   500      9951      0.00      0.00      0.00       0  node
Average:      500      9951      0.00      0.00      0.00       0  node

如果无法定位,可以去掉进程号看所有的进程,观察现象

# 间隔 1 秒输出多组数据 (这里是 20 组)

pidstat -d 1 20

通过 strace 进行跟踪

上一步拿到 pid 后可以用 strace 进行跟踪

sudo strace -p 11399

strace: Process 11399 attached
epoll_wait(11, [{EPOLLIN, {u32=40982992, u64=40982992}}], 16, 120000) = 1
read(13, ".\0\0\0(\0\0\0X\10\20\20\1j 1a44f465a3554d4f9"..., 262144) = 138
read(13, 0x7fff7523a380, 262144)        = -1 EAGAIN (Resource temporarily unavailable)
nanosleep({tv_sec=0, tv_nsec=10000000}, NULL) = 0
epoll_wait(11, [{EPOLLIN, {u32=40982992, u64=40982992}}], 16, 120000) = 1
read(13, ".\0\0\0(\0\0\0X\10\20\20\1j 2b7e857880da41f8b"..., 262144) = 138
read(13, 0x7fff7523a380, 262144)        = -1 EAGAIN (Resource temporarily unavailable)
nanosleep({tv_sec=0, tv_nsec=10000000}, NULL) = 0
epoll_wait(11,

ps检查进程状态

ps aux | grep 11399

root     11399  0.7  4.2 1114904 149348 ?      Sl   Jun13 537:27 /usr/local/qcloud/YunJing/YDEyes/YDService
ubuntu   23898  0.0  0.0  13776  1104 pts/4    S+   19:46   0:00 grep --color=auto 11399

如果以上方案都不行,就要用基于事件记录的动态追踪工具。

perf top 或 perf record

pref top -g

pref record -g
pref report

处理僵尸进程

找僵尸进程父进程

# -a 表示输出命令行选项
# p表PID
# s表示指定进程的父进程

pstree -aps 11399

systemd,1 --switched-root --system --deserialize 32
  └─YDLive,7059
      └─YDService,11399
          ├─sh,11521 -c sleep 100
          │   ├─{sh},11523
          │   ├─{sh},11524
          │   ├─{sh},11525
          │   ├─{sh},11526
          │   ├─{sh},11527
          │   ├─{sh},11528
          │   ├─{sh},11530
          │   └─{sh},9989
          ├─{YDService},11400
          ├─{YDService},11401
          ├─{YDService},11402
          ├─{YDService},11403
          ├─{YDService},11404
          ├─{YDService},11405
          ├─{YDService},11406
          ├─{YDService},11407
          ├─{YDService},11408
          ├─{YDService},11428
          ├─{YDService},11434
          ├─{YDService},11450
          ├─{YDService},11451
          ├─{YDService},11455
          ├─{YDService},11456
          ├─{YDService},11457
          ├─{YDService},11466
          ├─{YDService},11467
          ├─{YDService},11468
          ├─{YDService},11483
          ├─{YDService},11485
          ├─{YDService},11522
          └─{YDService},4319

再处理父进程就可以了。

小结

iowait 高不一定代表 I/O 有性能瓶颈。当系统中只有 I/O 类型的进程在运行时,iowait 也会很高,但实际上,磁盘的读写远没有达到性能瓶颈的程度。

因此,碰到 iowait 升高时,需要先用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问题,然后再找是哪些进程导致了 I/O。

等待 I/O 的进程一般是不可中断状态,所以用 ps 命令找到的 D 状态(即不可中断状态)的进程,多为可疑进程。有时在 I/O 操作后,进程又变成了僵尸进程,所以不能用 strace 直接分析这个进程的系统调用。这种情况下,需要用 perf 工具,来分析系统的 CPU 时钟事件,最终发现是直接 I/O 导致的问题。这时,再检查源码中对应位置的问题,就很轻松了。而僵尸进程的问题相对容易排查,使用 pstree 找出父进程后,去查看父进程的代码,检查 wait() / waitpid() 的调用,或是 SIGCHLD 信号处理函数的注册就行了。

Supongo que te gusta

Origin blog.csdn.net/TiktokLiveTool/article/details/132115146
Recomendado
Clasificación