0%

kill -9 不起作用

案例

在公司压测,因为担心磁盘读写影响性能,所以磁盘通过nfs挂载。之后发现挂载内容无法进行读取,于是乎想重新挂载,umount命令下去,提示Device is busy,那就是铁定挂载目录或者文件被进程占用了,随之查询到了进程,打算用kill pid让进程暂停,但发现没有成功,随后用kill -9 pid强制暂停,但发现也没成功,进程pid一直存在,进程也未退出。

原因

谷歌查询了下,得到了一个准确的回答。原文见refer。

kill不论发送任何信号,都是异步传递信号,内核传递信号给pid存在非常小的时间,但即便如此小的时间,也是需要进程腾出这么个时间点来接受,并处理,但如果进程当时处于阻止信号状态,那么发送过去的信号会被队列,等进程不在阻止信号后再传入,并且执行信号。

通常情况下,进程不会阻止信号,但是如果此时进程调用内核代码(系统调用),而内核代码是可以阻止信号传入的。当中断系统调用会导致内核中某处形成错误的数据结构,或者内核一些不变量被违反的时候,内核代码会阻塞所有信号传入。所以,若出现bug或其他异常情况触发了无限期的系统调用阻塞,那么就无法传递kill发送的信号。

在系统调用中被阻塞的进程,一般称为不可中断进程,通过ps或者top,查看状态为D的进程,一般磁盘读写数据的时候是处于不可中断进程状态。

一个典型的例子就是nfs挂载的情况,当server没有响应的时候,往往会一直处于不可中断情况。

解决方法

暂停server端和clinet端的nfs进程,重新挂载解决。

top ps查看不可中断进程

1
2
ps -eo pid,ppid,stat,pri,uid

进程状态常见标记符

  1. R 表示进程正在Cpu的就绪队列中,正在运行或者正在等待运行。
  2. D 是disk sleep缩写,也就是不可中断状态睡眠,一般表示进程正在和硬件交互,而交互过程不允许被其他进程或中断打断。
  3. Z 僵尸进程,实际上进程已经结束,但是父进程没有回收他的资源,比如进程描述符,pid等。
  4. S 是interruptible sleep缩写,表示可中断状态睡眠,表示进程因为等待某个事件而被挂起,当进程等到事件发生时,他会被唤醒进入R状态。
  5. I 是idle缩写,也是空闲状态,用在不可中断睡眠的内核线程上。前面的D是表示硬件交互导致的不可中断,但对某些内核线程来说,他们有可能实际上并没有任何负载,这边用Idle为了区分这种情况。D状态进程会导致平均负载升高,I状态的进程却不会。
  6. T 表示stopped状态,表示进程处于暂停状态(十字符病毒,一般都先对进程stop,然后排查问题),发送SIGSTP就可以让进程暂停,再发送SIGCONT信号,则恢复运行。
  7. t 表示跟踪状态。比如用gdb调试进程。
  8. X 表示Dead,进程已经消亡,所以在ps或者top里面无法看到。

refer:

https://cis.temple.edu/~ingargio/cis307/readings/signals.html
https://unix.stackexchange.com/questions/5642/what-if-kill-9-does-not-work
https://www.cnblogs.com/my_life/articles/5630903.html

坚持原创技术分享,您的支持将鼓励我继续创作!