1. 深度睡眠特点及存在原因
深度睡眠 TASK_UNINTERRUPTIBLE:不可被信号唤醒;
浅度睡眠 TASK_INTERRUPTIBLE:唤醒方式,等到需要的资源,响应信号;
深度睡眠场景:
有些场景是不能响应信号的,比如读磁盘过程是不能打断的,NFS 也是;
执行程序过程中,可能需要从磁盘读入可执行代码,假如在读磁盘过程中,又有代码需要从磁盘读取,就会造成嵌套睡眠。逻辑做的太复杂,所以读磁盘过程不允许打断,即只等待 IO 资源可用,不响应任何信号;
应用程序无法屏蔽也无法重载 SIGKILL 信号,深度睡眠可以不响应 SIGKILL kill- 9 信号;
深度睡眠案例
此时该进程读 IO 过程,是无法用 kill - 9 杀死的;
一般绝大部分场景,都设置为浅睡眠
ps aux: D+
深度睡眠进程显示 D + 状态
2. 深度睡眠对 load average 的影响
top load average:
cat /dev/global_fifo
Kill -2 pid
Kill -9 pid
无法杀死,load average 变大,CPU 依然空闲;
多加一个进程
cat /dev/global_fifo
load average 继续变大,CPU 依然空闲;
load
average:包括 CPU 消耗和 IO 的总预期,此时虽然不消耗 CPU,但是等待 IO 消耗了时间,load
average 显示的是随时间变化的平均负载预期;
D 状态会增加 load average;
对于同一个程序,不同执行环境:
执行性能 =APP(消耗 CPU)+DISK(I/ O 消耗);
3.TASK_KILLABLE
只响应致命信号 D 状态;
不跳转 APP 响应信号,不会产生递归睡眠;
__set_current_state(TASK_KILLABLE);
可以响应信号 9
kill -2 pid ? // 发现被杀死,什么原因呢
dmesg
git grep "complete_signal"
满足 sig_fatal,判断独占 signal_pending,符合条件,内核添加一个 SIGKILL 信号,导致 - 2 变成 -9
条件:
#define sig_fatal(t, signr) \\
(!siginmask(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \\
(t)->sighand->action[(signr)-1].sa.sa_handler == SIG_DFL)
满足信号:不忽略,也不是 stop,行为缺省。(缺省信号定义基本就是死,Core/Term 等)
那么添加 SIGKILL 信号;
与 fatal_signal() 必须 9 信号,不一样;
Ps: 如果应用层捕获了 2 信号,那么就不满足 sig_fatal,kill - 2 杀不死了;
综上, 满足 sig_fatal,kill - 2 可以杀 TASK_KILLABLE 进程;