iostat等命令看到的是系统级的统计,比如下例中我们看到/dev/sdb很忙,如果要追查是哪个进程导致的I/O繁忙,应该怎么办?

# iostat -xd
...
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdb               0.00     0.00 6781.67    0.00  3390.83     0.00     1.00     0.85    0.13    0.13    0.00   0.13  85.03
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
...

进程的内核数据结构中包含了I/O数量的统计:

struct task_struct {
...struct task_io_accounting ioac;
...
};

可以直接在 /proc/<pid>/io 中看到:

# cat /proc/3088/io
rchar: 125119 //在read(),pread(),readv(),sendfile等系统调用中读取的字节数
wchar: 632    //在write(),pwrite(),writev(),sendfile等系统调用中写入的字节数
syscr: 111    //调用read(),pread(),readv(),sendfile等系统调用的次数
syscw: 79     //调用write(),pwrite(),writev(),sendfile等系统调用的次数
read_bytes: 425984 //进程读取的物理I/O字节数,包括mmap pagein,在submit_bio()中统计的
write_bytes: 0     //进程写出的物理I/O字节数,包括mmap pageout,在submit_bio()中统计的
cancelled_write_bytes: 0 //如果进程截短了cache中的文件,事实上就减少了原本要发生的写I/O

我们关心的是实际发生的物理I/O,从上面的注释可知,应该关注 read_bytes 和 write_bytes。请注意这都是历史累计值,从进程开始执行之初就一直累加。如果要观察动态变化情况,可以使用 pidstat 命令,它就是利用了/proc/<pid>/io 中的原始数据计算单位时间内的增量:

# pidstat -d 2 2
Linux 3.10.0-229.14.1.el7.x86_64 (bj71s060)     11/16/2016      _x86_64_       (2 CPU)12:30:15 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
12:30:17 PM     0     14772   3362.25      0.00      0.00  dd12:30:17 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
12:30:19 PM     0     14772   3371.25      0.00      0.00  dd

另外还有一个常用的命令 iotop 也可以观察进程的动态I/O:

Actual DISK READ:       3.31 M/s | Actual DISK WRITE:       0.00 B/sTID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
14772 be/4 root        3.31 M/s    0.00 B/s  0.00 % 61.99 % dd if=/de~lag=direct1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % systemd -~rialize 242 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
...

pidstat 和 iotop 也有不足之处,它们无法具体到某个硬盘设备,如果系统中有很多硬盘设备,都在忙,而我们只想看某一个特定的硬盘的I/O来自哪些进程,这两个命令就帮不上忙了。怎么办呢?可以用上万能工具SystemTap。比如:我们希望找出访问/dev/sdb的进程,可以用下列脚本,它的原理是对submit_bio下探针:

#! /usr/bin/env stapglobal device_of_interestprobe begin {device_of_interest = $1printf ("device of interest: 0x%x\n", device_of_interest)
}probe kernel.function("submit_bio")
{dev = $bio->bi_bdev->bd_devif (dev == device_of_interest)printf ("[%s](%d) dev:0x%x rw:%d size:%d\n",execname(), pid(), dev, $rw, $bio->bi_size)
}

这个脚本需要在命令行参数中指定需要监控的硬盘设备号,得到这个设备号的方法如下:

# ll /dev/sdb
brw-rw----. 1 root disk 8, 16 Oct 24 15:52 /dev/sdbMajor number(12-bit):  8 i.e. 0x8
Minor number(20-bit): 16 i.e. 0x00010
合在一起得到设备号: 0x800010  注意是十六进制

执行脚本,我们看到:

# ./dev_task_io.stp 0x800010
device of interest: 0x800010
[dd](31202) dev:0x800010 rw:0 size:512
[dd](31202) dev:0x800010 rw:0 size:512
[dd](31202) dev:0x800010 rw:0 size:512
[dd](31202) dev:0x800010 rw:0 size:512
[dd](31202) dev:0x800010 rw:0 size:512
...

结果很令人满意,我们看到是进程号为31202的dd命令在对/dev/sdb进行读操作。

相关内容:

Linux的设备管理是和文件系统紧密结合的,把设备和文件关联起来,这样系统调用可以直接用操作文件一样的方法来操作设备。

各种设备都以文件的形式存放在/dev目录下,称为设备文件。

应用程序可以打开、关闭和读写这些设备文件,完成对设备的操作,就像操作普通的数据文件一样。

为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。

主设备号用来区分不同类型的设备,而次设备号用来区分同一类型内的多个设备(及其设备分区)。

查看主设备号:  cat /proc/devices
查看当前设备的主次设备号: ls -l /dev

一个Linux系统,当前所有注册设备的主设备号可以通过/proc接口查看:

[root@localhost lenky]# cat /proc/devices
Character devices:1 mem4 /dev/vc/04 tty4 ttyS5 /dev/tty5 /dev/console5 /dev/ptmx7 vcs10 misc13 input14 sound21 sg29 fb99 ppdev
116 alsa
128 ptm
136 pts
162 raw
180 usb
189 usb_device
202 cpu/msr
203 cpu/cpuid
251 hidraw
252 usbmon
253 bsg
254 rtcBlock devices:1 ramdisk2 fd
259 blkext7 loop8 sd9 md11 sr65 sd66 sd67 sd68 sd69 sd70 sd71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
253 device-mapper
254 mdp
[root@localhost lenky]#

字符设备与块设备的主设备号并不冲突,所有两个都可以有主设备号为1的设备,如果要继续查看次设备号,那么可以通过直接ls -l来查看,比如查看主设备号为8的设备的次设备号:

[root@localhost lenky]# ls -Rl /dev/* | grep " 8,"
brw-rw----. 1 root disk      8,   0 Jan 12 06:24 /dev/sda
brw-rw----. 1 root disk      8,   1 Jan 12 06:24 /dev/sda1
brw-rw----. 1 root disk      8,   2 Jan 12 06:24 /dev/sda2
brw-rw----. 1 root disk      8,  16 Jan 12 06:25 /dev/sdb
brw-rw----. 1 root disk      8,  17 Jan 12 06:25 /dev/sdb1
brw-rw----. 1 root disk      8,  32 Jan 12 06:29 /dev/sdc
brw-rw----. 1 root disk      8,  33 Jan 12 06:29 /dev/sdc1
brw-rw----. 1 root disk      8,  34 Jan 12 06:29 /dev/sdc2
brw-rw----. 1 root disk      8,  35 Jan 12 06:29 /dev/sdc3
[root@localhost lenky]#

上面的0,1,2,16,17等都是次设备号,用于区分标记各个sd硬盘或分区。查看系统所有的块设备:

[root@localhost lenky]# grep ^ /sys/class/block/*/dev
/sys/class/block/dm-0/dev:253:0
/sys/class/block/dm-1/dev:253:1
/sys/class/block/dm-2/dev:253:2
/sys/class/block/fd0/dev:2:0
/sys/class/block/loop0/dev:7:0
/sys/class/block/loop1/dev:7:1
/sys/class/block/loop2/dev:7:2
/sys/class/block/loop3/dev:7:3
/sys/class/block/loop4/dev:7:4
/sys/class/block/loop5/dev:7:5
/sys/class/block/loop6/dev:7:6
/sys/class/block/loop7/dev:7:7
/sys/class/block/ram0/dev:1:0
/sys/class/block/ram10/dev:1:10
/sys/class/block/ram11/dev:1:11
/sys/class/block/ram12/dev:1:12
/sys/class/block/ram13/dev:1:13
/sys/class/block/ram14/dev:1:14
/sys/class/block/ram15/dev:1:15
/sys/class/block/ram1/dev:1:1
/sys/class/block/ram2/dev:1:2
/sys/class/block/ram3/dev:1:3
/sys/class/block/ram4/dev:1:4
/sys/class/block/ram5/dev:1:5
/sys/class/block/ram6/dev:1:6
/sys/class/block/ram7/dev:1:7
/sys/class/block/ram8/dev:1:8
/sys/class/block/ram9/dev:1:9
/sys/class/block/sda1/dev:8:1
/sys/class/block/sda2/dev:8:2
/sys/class/block/sda/dev:8:0
/sys/class/block/sdb1/dev:8:17
/sys/class/block/sdb/dev:8:16
/sys/class/block/sdc1/dev:8:33
/sys/class/block/sdc2/dev:8:34
/sys/class/block/sdc3/dev:8:35
/sys/class/block/sdc/dev:8:32
/sys/class/block/sr0/dev:11:0
[root@localhost lenky]#

关于每个主设备号:次设备号对应设备的功能在Linux帮助文档里可以找到:http://lxr.linux.no/#linux+v2.6.38.8/Documentation/devices.txt

在内核2.6.9之后,Linux系统上出现了一种名为device-mapper的存储映射机制,这种机制的作用简单来说就是给用户提供简单方便而又丰富的存储管理接口,在这种机制以及相关工具的帮助下,用户能够方便的自定义存储资源管理策略。

通过一些映射规则,device-mapper机制能够从原有的物理磁盘或逻辑磁盘中划分映射出新的逻辑磁盘,可以看到这是一个递归的映射机制,理论上可无限迭代。举个例子,系统有物理磁盘A和B,从物理磁盘A中映射出新的逻辑磁盘C、D、E,从物理磁盘B中映射出新的逻辑磁盘F、G,又可以从物理磁盘A和逻辑磁盘F中映射出新的逻辑磁盘H,等等。关于这方面,请参考:http://www.ibm.com/developerworks/cn/linux/l-devmapper/、http://sources.redhat.com/dm/等资源,不管是原物理磁盘还是通过device-mappe机制映射出来的新逻辑磁盘,在Linux操作系统看来都一样,一切皆文件,复杂逻辑被隔离在底部。

[root@localhost lenky]# ls -Rl /dev/* | grep " 8,"
brw-rw----. 1 root disk      8,   0 Jan 12 06:24 /dev/sda
brw-rw----. 1 root disk      8,   1 Jan 12 06:24 /dev/sda1
brw-rw----. 1 root disk      8,   2 Jan 12 06:24 /dev/sda2

一般说的各个分区相加等于硬盘,有个隐含说明就是硬盘内各个分区的硬盘存储空间容量相加等于硬盘的硬盘存储空间容量。

一个硬盘有一个描述硬盘的信息,而一个分区有一描述分区的信息,将硬盘内各个分区的描述分区的信息拼接在一起也得不到关于硬盘的信息,所以给硬盘配上一个次设备号是有必要不多余的。

[root@localhost lenky]# ls -Rl /dev/* | grep " 8,"
brw-rw----. 1 root disk      8,   0 Jan 12 06:24 /dev/sda
brw-rw----. 1 root disk      8,   1 Jan 12 06:24 /dev/sda1
brw-rw----. 1 root disk      8,   2 Jan 12 06:24 /dev/sda2
brw-rw----. 1 root disk      8,  16 Jan 12 06:25 /dev/sdb
brw-rw----. 1 root disk      8,  17 Jan 12 06:25 /dev/sdb1
brw-rw----. 1 root disk      8,  32 Jan 12 06:29 /dev/sdc
brw-rw----. 1 root disk      8,  33 Jan 12 06:29 /dev/sdc1
brw-rw----. 1 root disk      8,  34 Jan 12 06:29 /dev/sdc2
brw-rw----. 1 root disk      8,  35 Jan 12 06:29 /dev/sdc3

我们看到/dev/sd*设备名的设备类型(即指的是IDE硬盘),这里有三个不同的IDE硬盘,其主设备号以及其分区的主设备号都是8。

转载于:https://www.cnblogs.com/felixzh/p/9035103.html

DISK 100% BUSY,谁造成的?(ok)相关推荐

  1. Linux disk 100% busy,谁造成的?

    disk 100% busy,谁造成的? 2016/11/16 vmunix iostat等命令看到的是系统级的统计,比如下例中我们看到/dev/sdb很忙,如果要追查是哪个进程导致的I/O繁忙,应该 ...

  2. asynchronous aof fsync is taking too long (disk is busy?)

    一.背景 线上redis的监控数据不太好看,领导觉得看看能不能优化下,分析下什么情况,于是就..... 二.现象 看到redis日志里面一堆这个,于是就开始了分析排查 先放一张前后对比图吧 三.排查 ...

  3. Redis源码分析:AOF策略与时间触发任务

    时间周期性任务与AOF策略 周期性任务在分析启动流程与服务端处理的过程的时候,描述过有关时间任务的处理过程,在Redis内部事件驱动的过程中,有通过时间来进行事件的触发与处理机制,本文会先分析一下主要 ...

  4. 当 Redis 发生高延迟时,到底发生了什么

    来自:程序员厉小冰 Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多.但是 Redis 也会发生延迟时,这是就需要我们对其产生原因有深刻的了解,以 ...

  5. 深入学习Redis持久化

    一.Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义. 我们知道,在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常 ...

  6. PostgreSQL 异步IO实测

    标签 PostgreSQL , effective_io_concurrency , 异步IO 背景 异步IO的目的是充分发挥块设备的吞吐能力,让块设备处于更繁忙的工作状态(一次连续摄取更多的块),而 ...

  7. windows 系统监视器 以及建议阀值

    常用的windows计数器及性能分析方法 一.常用的windows计数器 processor %processor time    建议阈值85% memory Available bytes    ...

  8. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  9. Redis 高可用特性之 “持久化” 详解

    在之前的文章中,介绍了<Redis的内存模型>,从这篇文章开始,将依次介绍 Redis 高可用相关的知识--持久化.复制(及读写分离).哨兵.以及集群. 本文将先说明上述几种技术分别解决了 ...

最新文章

  1. Linux 环境 搭建Git 服务器,并且修改SSH端口使用
  2. java makedir用法_Java Files.makeDir方法代码示例
  3. python学起来难不难-新手学python数据分析难不难?
  4. js数组的声明与应用
  5. leetcode1029. 两地调度(贪心算法)
  6. Setup SQL Server 2008 Maintenance Plan Email Notifications
  7. Java基础学习总结(85)——Java中四种线程安全的单例模式实现方式
  8. 2020级C语言大作业 - 火柴人打羽毛球
  9. 一种使用SOC精确控制脉冲的方法
  10. 入门级都能看懂的softmax详解
  11. 仿生软体机器人就业咋样_SRT近亿元B轮融资,中国软体机器人技术从空白到全球领先...
  12. lzg_ad:EWF启用常见问题及解决方案
  13. SQL语句一对多查询
  14. java lucene 站内搜索_完整的站内搜索Demo(Lucene.Net+盘古分词)
  15. MSSQL · 实现分析 · SQL Server实现审计日志的方案探索
  16. Spark 的情感分析
  17. 几行CSS让你的页面立体起来
  18. B端市场分析报告(一)
  19. Python pip 修改镜像源为豆瓣源的两种方法
  20. JTAG,PLL ,ICE

热门文章

  1. mysql5.7只安装服务端_Windows Mysql5.7.11 服务端安装详解
  2. linux启动脚本 范本,Linux—微服务启停shell脚本编写模板
  3. cpp 怎么连接mysql_C++连接mysql数据库的两种方法
  4. java 数组map_java中 数组 list map之间的互转
  5. java linux urlencode_iOS urlEncode编码解码(非过时方法,已解决)
  6. 不止面试题,笔记源码统统都有
  7. 2021-08-27 思考:1000瓶药水,1瓶有毒,老鼠毒发24h,如何用最少的老鼠在24h内找出毒药?
  8. 【响应式Web前端设计】Register Demo
  9. python【力扣LeetCode算法题库】206-反转链表
  10. Python程序设计题解【蓝桥杯官网题库】 DAY8-基础练习