确定“的数量”;逻辑的;在Linux系统中读取/写入的字节数

确定“的数量”;逻辑的;在Linux系统中读取/写入的字节数,linux,performance,io,Linux,Performance,Io,我想确定所有进程通过系统调用(如read()和write())逻辑读取/写入的字节数。这与实际从存储层获取的字节数(由iotop等工具显示)不同,因为它包括(例如)命中页面缓存的读取,并且在识别写入时也不同:逻辑写入IO在发出write调用时立即发生,而实际的物理IO可能会在一段时间后发生,这取决于各种因素(Linux通常会在一段时间后缓冲写入和执行物理IO) 我知道如何在每个进程的基础上执行此操作(请参见示例),但不知道如何获取系统范围的计数。下面是一个跟踪逻辑IO的SystemTap脚本。它

我想确定所有进程通过系统调用(如
read()
write()
)逻辑读取/写入的字节数。这与实际从存储层获取的字节数(由iotop等工具显示)不同,因为它包括(例如)命中页面缓存的读取,并且在识别写入时也不同:逻辑写入IO在发出
write
调用时立即发生,而实际的物理IO可能会在一段时间后发生,这取决于各种因素(Linux通常会在一段时间后缓冲写入和执行物理IO)


我知道如何在每个进程的基础上执行此操作(请参见示例),但不知道如何获取系统范围的计数。

下面是一个跟踪逻辑IO的SystemTap脚本。它基于

#/usr/bin/env stap
#traceio.stp
#版权所有(C)2007红帽有限公司,尤金·特奥
#版权所有(C)2009 Kai Meyer
#修正了一个错误,允许这个运行更长时间
#并增加了人性化的阅读功能
#
#这个程序是自由软件;您可以重新分发和/或修改它
#根据GNU通用公共许可证第2版的条款
由自由软件基金会发表。
#
全局读写
探测vfs.read.return{
如果($return>0){
读取+=$return
}
}
探测vfs.write.return{
如果($return>0){
写入+=$return
}
}
函数可读(字节){
如果(字节数>1024*1024*1024){
返回sprintf(“%d GiB”,字节/1024/1024/1024)
}else if(字节>1024*1024){
返回sprintf(“%d MiB”,字节/1024/1024)
}else if(字节>1024){
返回sprintf(“%d KiB”,字节/1024)
}否则{
返回sprintf(“%d B”,字节)
}
}
探针计时器.s(1){
printf(“读取:%12s写入:%12s\n”、可读(读取)、可读(写入))
#注意,我们不会将读取和写入归零,
#因此,自脚本启动以来,这些值是累积的。
}

如果您想使用
/proc
文件系统来计算总计数(而不是每秒计数),这非常简单

这也适用于非常旧的内核(在Debian Squeeze 2.6.32内核上测试)

对于系统范围,只需将所有进程的数字相加,但这只在短期内就足够了,因为随着进程的死亡,它们的统计数据将从内存中删除。您需要启用流程记帐才能保存它们

内核源文件中记录了这些文件的含义:

rchar-I/O计数器:读取字符

此任务导致的字节数 从存储器中读取。这仅仅是它所包含的字节的总和 进程传递给read()和pread()。它包括tty IO之类的东西 而且它不受实际的物理磁盘IO是否 必需(可能已从pagecache满足读取要求)

wchar-I/O计数器:写入字符

此任务具有的字节数 导致或应导致写入磁盘。类似的警告也适用 这里和阿尔卡一样

syscr-I/O计数器:读取系统调用

尝试计数读取I/O的数量 操作,即read()和pread()之类的系统调用

syscw-I/O计数器:写入系统调用

尝试计数写入I/O的数量 操作,即write()和pwrite()等系统调用

读取字节-I/O计数器:读取字节

尝试计算所需的字节数 这个过程确实导致从存储层获取数据。 在submit_bio()级别完成,因此对于块备份 文件系统

写入字节-I/O计数器:写入的字节

尝试计算所需的字节数 此过程导致发送到存储层。这是在 页面弄脏时间

已取消写入字节

这里最大的误差是截断。如果进程向文件写入1MB 然后删除文件,它实际上不会执行写操作。但是它 将被视为导致1MB写入。换句话说 字:此进程导致不发生的字节数,由 截断页面缓存。任务也可能导致“负面”IO


谢谢,但我无法在此应用程序中使用systemtap。我的首选方法是使用/proc文件系统。@BeeOnRope,然后您可以检查。否则,您将需要创建一个内核模块,因为据我所知,无法从
/proc
中检查聚合的
read()
write()
。这些字段代表什么?实际上,我对每个进程的编号很感兴趣,所以如果是逻辑IO,这将非常好,但我找不到这些字段的含义。我已经添加了解释。前两个字段是来自进程的逻辑请求,无论它们是否导致磁盘I/O。很抱歉,这是一个很好的答案,也是我一直在寻找的,但SO的超严格赏金系统意味着我错过了为您分配全部赏金的机会,因为我在赏金到期时不在。所以你必须对25个代表感到满意,我想。。。
#! /usr/bin/env stap
# traceio.stp
# Copyright (C) 2007 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
# Copyright (C) 2009 Kai Meyer <kai@unixlords.com>
#   Fixed a bug that allows this to run longer
#   And added the humanreadable function
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#

global reads, writes

probe vfs.read.return {
  if ($return > 0) {
    reads += $return
  }
}

probe vfs.write.return {
  if ($return > 0) {
    writes += $return
  }
}

function humanreadable(bytes) {
  if (bytes > 1024*1024*1024) {
    return sprintf("%d GiB", bytes/1024/1024/1024)
  } else if (bytes > 1024*1024) {
    return sprintf("%d MiB", bytes/1024/1024)
  } else if (bytes > 1024) {
    return sprintf("%d KiB", bytes/1024)
  } else {
    return sprintf("%d   B", bytes)
  }
}

probe timer.s(1) {
  printf("reads: %12s writes: %12s\n", humanreadable(reads), humanreadable(writes))
  # Note we don't zero out reads and writes,
  # so the values are cumulative since the script started.
}
# cat /proc/1979/io
rchar: 111195372883082
wchar: 10424431162257
syscr: 130902776102
syscw: 6236420365
read_bytes: 2839822376960
write_bytes: 803408183296
cancelled_write_bytes: 374812672