Linux进程状态:S (TASK_INTERRUPTIBLE),可中断的睡眠状态


处于这个状态的进程因为等待某某事件的发生(比如等待socket连接、等待信号量),而被挂起。这些进程的task_struct结构被放入对应事件的等待队列中。当这些事件发生时(由外部中断触发、或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒。

通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程都处于TASK_INTERRUPTIBLE状态(除非机器的负载很高)。毕竟CPU就这么一两个,进程动辄几十上百个,如果不是绝大多数进程都在睡眠,CPU又怎么响应得过来。

Linux进程状态:D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态


与TASK_INTERRUPTIBLE状态类似,进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指的并不是CPU不响应外部硬件的中断,而是指进程不响应异步信号。

绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的。否则你将惊奇的发现,kill -9竟然杀不死一个正在睡眠的进程了!于是我们也很好理解,为什么ps命令看到的进程几乎不会出现TASK_UNINTERRUPTIBLE状态,而总是TASK_INTERRUPTIBLE状态。

而TASK_UNINTERRUPTIBLE状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。

在进程对某些硬件进行操作时(比如进程调用read系统调用对某个设备文件进行读操作,而read系统调用最终执行到对应设备驱动的代码,并与对应的物理设备进行交互),可能需要使用TASK_UNINTERRUPTIBLE状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的状态。这种情况下的TASK_UNINTERRUPTIBLE状态总是非常短暂的,通过ps命令基本上不可能捕捉到。

不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的I/O响应,也就是我们在ps命令中看到的D状态(Uninterruptible Sleep,也称为Disk Sleep)的进程。

比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。

所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。

linux系统中也存在容易捕捉的TASK_UNINTERRUPTIBLE状态。执行vfork系统调用后,父进程将进TASK_UNINTERRUPTIBLE状态,直到子进程调用exit或exec 通过下面的代码就能得到处于TASK_UNINTERRUPTIBLE状态的进程:

[root@localhost ~]# cat test.c
void main() {
if (!vfork()) sleep(100);
} [root@localhost ~]# gcc -o test  test.c[root@localhost ~]# ./test [root@localhost ~]# ps -aux | grep test
root      19454  0.0  0.0   4212   352 pts/6    D+   10:02   0:00 ./test
root      19455  0.0  0.0   4212   352 pts/6    S+   10:02   0:00 ./test

进程为什么会被置于uninterruptible sleep状态呢?


处于uninterruptiblesleep状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统已经不可访问了(由down掉的NFS服务器引起的D状态)。

正是因为得不到IO的相应,进程才进入了uninterruptible sleep状态,所以要想使进程从uninterruptible sleep状态恢复,就得使进程等待的IO恢复,比如如果是因为从远程挂载的NFS卷不可访问导致进程进入uninterruptible sleep状态的,那么可以通过恢复该NFS卷的连接来使进程的IO请求得到满足。

D状态,往往是由于 I/O 资源得不到满足,而引发等待


在内核源码 fs/proc/array.c 里,其文字定义为“ "D (disk sleep)", /* 2 */ ”(由此可知 D 原是Disk的打头字母),对应着 include/linux/sched.h 里的“ #define TASK_UNINTERRUPTIBLE 2 ”。举个例子,当 NFS 服务端关闭之时,若未事先 umount 相关目录,在 NFS 客户端执行 df 就会挂住整个登录会话,按 Ctrl+C 、Ctrl+Z 都无济于事。断开连接再登录,执行 ps axf 则看到刚才的 df 进程状态位已变成了 D ,kill -9 无法杀灭。正确的处理方式,是马上恢复 NFS 服务端,再度提供服务,刚才挂起的 df 进程发现了其苦苦等待的资源,便完成任务,自动消亡。若 NFS 服务端无法恢复服务,在 reboot 之前也应将 /etc/mtab 里的相关 NFS mount 项删除,以免 reboot 过程例行调用 netfs stop 时再次发生等待资源,导致系统重启过程挂起。

Nginx举例一则,只是举个例子大概看看就行


第二客户端机器我们将运行另一个副本的wrk,但是这个脚本我们使用50的并发连接来请求相同的文件。因为这个文件被经常访问的,它将保持在内存中。在正常情况下,NGINX很快的处理这些请求,但是工作线程如果被其他的请求阻塞性能将会下降。所以我们暂且叫它“加载恒定负载”。

性能将由服务器上ifstat监测的吞吐率(throughput)和从第二台客户端获取的wrk结果来度量。

现在,没有线程池的第一次运行不会给我们带来非常令人兴奋的结果:

% ifstat -bi eth2
eth2
Kbps in  Kbps out
5531.24  1.03e+06
4855.23  812922.7
5994.66  1.07e+06
5476.27  981529.3
6353.62  1.12e+06
5166.17  892770.3
5522.81  978540.8
6208.10  985466.7
6370.79  1.12e+06
6123.33  1.07e+06

如你所见,上述的配置可以产生一共1G的流量,从top命令上我们可以看到所有的工作线程在阻塞io上花费了大量的时间(下图D状态):

top - 10:40:47 up 11 days,  1:32,  1 user,  load average: 49.61, 45.77 62.89
Tasks: 375 total,  2 running, 373 sleeping,  0 stopped,  0 zombie
%Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 67.7 id, 31.9 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  49453440 total, 49149308 used,   304132 free,    98780 buffers
KiB Swap: 10474236 total,    20124 used, 10454112 free, 46903412 cached MemPID USER     PR  NI    VIRT    RES     SHR S  %CPU %MEM    TIME+ COMMAND4639 vbart    20   0   47180  28152     496 D   0.7  0.1  0:00.17 nginx4632 vbart    20   0   47180  28196     536 D   0.3  0.1  0:00.11 nginx4633 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.11 nginx4635 vbart    20   0   47180  28136     480 D   0.3  0.1  0:00.12 nginx4636 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.14 nginx4637 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.10 nginx4638 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.12 nginx4640 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.13 nginx4641 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.13 nginx4642 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.11 nginx4643 vbart    20   0   47180  28276     536 D   0.3  0.1  0:00.29 nginx4644 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.11 nginx4645 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.17 nginx4646 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.12 nginx4647 vbart    20   0   47180  28208     532 D   0.3  0.1  0:00.17 nginx4631 vbart    20   0   47180    756     252 S   0.0  0.1  0:00.00 nginx4634 vbart    20   0   47180  28208     536 D   0.0  0.1  0:00.11 nginx<4648 vbart    20   0   25232   1956    1160 R   0.0  0.0  0:00.08 top
25921 vbart    20   0  121956   2232    1056 S   0.0  0.0  0:01.97 sshd
25923 vbart    20   0   40304   4160    2208 S   0.0  0.0  0:00.53 zsh

在这种情况下,吞吐率受限于磁盘子系统,而CPU在大部分时间里是空转状态的。从wrk获得的结果来看也非常低:

Running 1m test @ http://192.0.2.1:8000/1/1/112 threads and 50 connectionsThread Stats   Avg    Stdev     Max  +/- StdevLatency     7.42s  5.31s   24.41s   74.73%Req/Sec     0.15    0.36     1.00    84.62%488 requests in 1.01m, 2.01GB read
Requests/sec:      8.08
Transfer/sec:     34.07MB

请记住,文件是从内存送达的!第一个客户端的200个连接创建的随机负载,使服务器端的全部的工作进程忙于从磁盘读取文件,因此产生了过大的延迟,并且无法在合适的时间内处理我们的请求。

Linux 进程状态D Disk Sleep相关推荐

  1. 【Linux操作系统】Linux进程状态和两个特殊进程

    文章目录 一.一套普适性的进程状态理论 1.运行 2.阻塞 3.挂起 二.一套具体的Linux进程状态 1.R-运行 2.S-睡眠 3.T-暂停 5.t-被追踪 三.僵尸进程和孤儿进程 1.僵尸进程 ...

  2. Linux进程状态解析之R、S、D、T、Z、X

    文章转载自:http://hi.baidu.com/shining_pc/item/21abcb32a4d2d484c3cf2950 Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程 ...

  3. 【Linux 内核】调度器 ① ( 调度器概念 | 调度器目的 | 调度器主要工作 | 调度器位置 | 进程优先级 | 抢占式调度器 | Linux 进程状态 | Linux 内核进程状态 )

    文章目录 一.调度器 0.调度器概念 1.调度器目的 2.调度器主要工作 3.调度器位置 4.进程优先级 5.抢占式调度器 二.Linux 内核进程状态 API 简介 三.Linux 进程状态 一.调 ...

  4. Linux进程状态解析 之 R、S、D、T、Z、X (主要有三个状态)

    linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态. Linux进程状态:R (TASK_RUNNING),可执行状态. 只有在该状 ...

  5. Linux进程状态解析

    Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有 不同的状态. Linux进程状态:R (TASK_RUNNING),可执行状态. 只有在该 ...

  6. Linux下进程状态转换,Linux进程状态转换图

    Linux进程状态 Linux内核中的进程状态 ◆运行状态(TASK_RUNNING) 指正在被CPU运行或者就绪的状态.这样的进程被成为runnning进程.运行态的进程可以分为3种情况:内核运行态 ...

  7. linux进程状态详解

    Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态. Linux进程状态:R (TASK_RUNNING),可执行状态 只有在该状态 ...

  8. Linux进程状态及其相互转换

    Linux进程状态及其相互转换 Linux中,进程有以下6中状态. Linux系统中的进程主要有以下六种状态. (1)TASK_RUNNING(可运行状态).正在运行的进程或在可运行进程队列(run_ ...

  9. 操作系统原理,进程的基本状态,运行态,就绪态,等待态与转换模型,进程的其他状态,创建,终止,挂起与转换模型,Linux进程状态模型示例

    操作系统原理,进程的基本状态,运行态,就绪态,等待态与转换模型,进程的其他状态,创建,终止,挂起与转换模型,Linux进程状态模型示例 一.进程的三种基本状态: 运行态,就绪态,等待态 1.运行态: ...

最新文章

  1. 自动飞行控制系统_波音737MAX,安全评估竟是自己做的!飞行员仅用iPad学习驾驶!...
  2. websocket ws 协议 简介
  3. Xor Path - 牛客
  4. LeetCode Ugly Number II(丑数的计算)
  5. 常用正则表达式汇总(数字匹配/字符匹配/特殊匹配)
  6. datatable里添加一个标识列
  7. swift解析html数据类型,ios-Swift:以标签或textVi显示HTML数据
  8. 计算机网络应用云计算,计算机网络云计算的类型
  9. php加密数据解密,php 数据加密解密
  10. 应用zip压缩的javascript以及Egret H5游戏实战
  11. 美团自研无人机登场:15分钟配送到家
  12. Centos7的 git: 未找到命令解决方法
  13. [Java] 蓝桥杯ADV-213 算法提高 3-2求存款
  14. atitit.极光消息推送服务器端开发实现推送  jpush v3. 总结o7p
  15. ITIL 4知识系列之ITIL4的设计框架解析
  16. DCE/MS RPC旁窥
  17. 考勤打卡不如自我约束
  18. Ubuntu 18.04 ibus安装配置中文拼音输入法
  19. (十九)债券定价与债券收益率的计算
  20. Windows 10 驱动开发 及 驱动签名

热门文章

  1. 关于AndroidID的记录:AndroidID什么时候会改变/AndroidID做唯一标识符是否可行
  2. hypermesh 圆周阵列-插件
  3. 解决导入markdown时本地图片无法显示问题——图床
  4. 巧用工具将ppt转换成Word
  5. 阿里云Elasticsearch性能优化实践
  6. java excel 透视_java基于poi导出excel透视表代码实例
  7. 样品制备丨G-Biosciences Tube-O-CONCENTRATOR 方案
  8. 浅谈ThreadLocal
  9. SQL的函数---3th
  10. 三问道出新媒体运营入门的基本操作,你不会不知道吧?