首页 > 系统相关 >系统中出现大量不可中断进程和僵尸进程怎么办?

系统中出现大量不可中断进程和僵尸进程怎么办?

时间:2023-08-04 20:14:46浏览次数:29  
标签:20 僵尸 中断 0.0 0.00 YDService 进程 9951

进程状态

通过top命令,我们可以看到进程的状态(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

进程的状态共有以下几种:

  • R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。

  • D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。

  • Z 是 Zombie 的缩写,也就是僵尸状态,进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。

  • S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。

  • I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。

  • T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。

  • X,也就是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。

不可中断状态

先看不可中断状态,这其实是为了保证进程数据与硬件状态一致,并且正常情况下,不可中断状态在很短时间内就会结束。所以,短时的不可中断状态进程,我们一般可以忽略。

但如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,你就得注意下,系统是不是出现了 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 信号处理函数的注册就行了。

标签:20,僵尸,中断,0.0,0.00,YDService,进程,9951
From: https://www.cnblogs.com/lurenjiashuo/p/linux-disk-sleep-zombie-process.html

相关文章

  • 为什么有了gil锁还要互斥锁,进程,线程和协程 ,什么是鸭子类型
    1为什么有了gil锁还要互斥锁-gil锁,全局解释器锁,线程需要运行需要得到gil锁,gil锁不能控制用户级别的安全-#互斥锁,为了保证多线程并发操作数据而设置的锁,保证在加锁和释放锁之间,其他线程不能操作,让并行变成串行,牺牲效率-起两个线程。执行任务,x=x+1,x开始等于0-1第一个线程过来......
  • 三菱FXPLC 中断服务
    一、中断是什么所谓中断,是指PLC按顺序执行程序扫描的过程中,当有需要立即反应的请求发出时,立即中断当前执行的扫描工作,优先地去执行请求所指定的服务工作。服务工作完成后,再回到刚才被中断的地方继续往下执行程序扫描工作。换句话说,中断服务就像是个磨人的小妖精,时不时......
  • 植物大战僵尸修改器制作--从入门到入土
    目录基础准备基址偏移表常规项目卡槽植物种植无冷却无限阳光浓雾透视基本原理HOOK除雾代码种植植物基本原理远程线程注入dll函数远程线程卸载dll函数关键dll函数失败代码远程线程代码注入(推荐)种植僵尸基本原理种植僵尸函数--dll注入版远程代码注入版完整代码参考资料基础准备......
  • python-windows命令行启动appium及杀掉对应接口进程
    文章目录windows命令行启动appium及杀掉对应接口进程一.环境配置1.安装命令行版appium2.安装appium-doctor检测3.python安装Appium-Python-Client:4.定位uiautomatorviewer.bat5.查看主包名主类名Activity二.python-appium启动app1.appium启动一加计算器相关参数:2.windows查看端口......
  • 进程,线程和协程;为什么有了GIL锁还要互斥锁;多态和多态性;鸭子类型
    进程,线程和协程;为什么有了GIL锁还要互斥锁;多态和多态性;鸭子类型为什么有了GIL锁还要互斥锁1.GIL本身就是一个大的互斥锁2.同一个进程下资源是共享的,也就是说多条线程可以操作同一个变量3.多个线程可以操作同一个变量就会出现数据安全问题4.临界区:指一段代码或一段程序片段,需......
  • Linux Shell实现模拟多进程并发执行
        在bash中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。我们就先实现第一种情况:实例一:正常情况脚本———————————————————————————–#......
  • java进程占用系统内存高,排查解决 _
    java进程占用系统内存高,排查解决_ 故障:今天许多开发反馈测试平台卡,访问不了,第一感觉判断是服务器内存爆了,或者cpu占用过高,上服务器看了一下,确实是内存爆了。然后开始定位问题原因,因为阿里这边安全的原因,具体的图片就不方便上传了,拿网上的图来说 使用top命令查看......
  • 隐藏进程
    importctypes#定义WindowsAPI函数importtimeuser32=ctypes.WinDLL("user32")user32.ShowWindow.argtypes=[ctypes.c_void_p,ctypes.c_int]user32.ShowWindow.restype=ctypes.c_int#隐藏进程函数defhide_process():#获取当前进程的窗口句柄hwnd......
  • 为什么有了gil锁还要互斥锁、 进程,线程和协程 、什么是鸭子类型
    目录1为什么有了gil锁还要互斥锁互斥锁保证数据安全2进程,线程和协程在哪用过3什么是鸭子类型1为什么有了gil锁还要互斥锁gil:全局解释器锁,线程要执行,必须先获得到gil锁,才能执行互斥锁:为了保证多线程并发操作数据(变量)而设置的锁,保证在加锁和释放锁之间,其他线程不能操作gi......
  • process explorer 可以查看进程的网络通信情况 收发字节数
      网络里可以查看的选项:  DLL里可以看到: ......