IOのread、writeがプロセスごとに取れる
ゴールデンウィーーークもそろそろ終了、アルチューハイマーになったこの体を元にもどすのに、リハビリが必要な時期に...どうでもいいですが...
いきなり話、違う話
iostatとかでも取れるんだけど、デバイスごとのIOの統計が上がってくるので、もうちょい細かいレイヤーでそれが見たいときがある。なんか無いかとportageツリーをさまよっていたら、iotopなるものをを発見。
カーネルのオプションが多分必要なので、確認してね
CONFIG_TASK_IO_ACCOUNTING CONFIG_TASK_DELAY_ACCT CONFIG_TASKSTATS CONFIG_VM_EVENT_COUNTERS
で、iotopをインストール
cuomo@ugui7 ~ $ emerge sys-process/iotop
暇なので、kernelの方も覗いてみた
触りだけですが、興味本位に覗いてみました。
やっぱりプロセスごとに取れるのでtask_struct構造体に「struct task_io_accounting」がぶら下がっていて
struct task_struct { .. .. struct task_io_accounting ioac; .. .. };
struct task_io_accounting { #ifdef CONFIG_TASK_XACCT /* bytes read */ u64 rchar; /* bytes written */ u64 wchar; /* # of read syscalls */ u64 syscr; /* # of write syscalls */ u64 syscw; #endif /* CONFIG_TASK_XACCT */ #ifdef CONFIG_TASK_IO_ACCOUNTING /* * The number of bytes which this task has caused to be read from * storage. */ u64 read_bytes; /* * The number of bytes which this task has caused, or shall cause to be * written to disk. */ u64 write_bytes; /* * A task can cause "negative" IO too. If this task truncates some * dirty pagecache, some IO which another task has been accounted for * (in its write_bytes) will not be happening. We _could_ just * subtract that from the truncating task's write_bytes, but there is * information loss in doing that. */ u64 cancelled_write_bytes; #endif /* CONFIG_TASK_IO_ACCOUNTING */ };
これが、プロセスごとに集計されるIOの情報を管理する構造体らしい、「read_bytes」と「write_bytes」がそれ
これが特定の処理を通ったときに加算されていくらしい
*** linux-4.10.11-gentoo/fs/block_dev.c: __blkdev_direct_IO_simple[242] task_io_account_write(ret); __blkdev_direct_IO[377] task_io_account_write(bio->bi_iter.bi_size); *** linux-4.10.11-gentoo/fs/direct-io.c: submit_page_section[800] task_io_account_write(len); *** linux-4.10.11-gentoo/fs/iomap.c: iomap_dio_actor[812] task_io_account_write(bio->bi_iter.bi_size); *** linux-4.10.11-gentoo/fs/nfs/direct.c: nfs_file_direct_write[1003] task_io_account_write(count); *** linux-4.10.11-gentoo/mm/page-writeback.c: account_page_dirtied[2436] task_io_account_write(PAGE_SIZE);
ディスクの書込みだけ抜粋してみた、該当するプロセスがページを書いたり、nfsへ書いたりした場合に、加算されているようです。
nfsの場合って、ネットワーク越しのディスクに書き込んだ場合は、書込みバイト数として加算しない?
などと、思ったりしてます、試してませんので分かりません。
/proc で確認する
* /fs/proc/base.c:
... def CONFIG_TASK_IO_ACCOUNTING ONE("io", S_IRUSR, proc_tid_io_accounting) #ifdef CONFIG_TASK_IO_ACCOUNTING ONE("io", S_IRUSR, proc_tid_io_accounting), ...
で定義されてて、seq_printf経由で確認できる
static int do_io_accounting(struct task_struct *task, struct seq_file *m, int whole) { struct task_io_accounting acct = task->ioac; unsigned long flags; int result; result = mutex_lock_killable(&task->signal->cred_guard_mutex); if (result) return result; if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { result = -EACCES; goto out_unlock; } if (whole && lock_task_sighand(task, &flags)) { struct task_struct *t = task; task_io_accounting_add(&acct, &task->signal->ioac); while_each_thread(task, t) task_io_accounting_add(&acct, &t->ioac); unlock_task_sighand(task, &flags); } seq_printf(m, "rchar: %llu\n" "wchar: %llu\n" "syscr: %llu\n" "syscw: %llu\n" "read_bytes: %llu\n" "write_bytes: %llu\n" "cancelled_write_bytes: %llu\n", (unsigned long long)acct.rchar, (unsigned long long)acct.wchar, (unsigned long long)acct.syscr, (unsigned long long)acct.syscw, (unsigned long long)acct.read_bytes, (unsigned long long)acct.write_bytes, (unsigned long long)acct.cancelled_write_bytes); result = 0; out_unlock: mutex_unlock(&task->signal->cred_guard_mutex); return result; }
なので、「/proc/PID/io」で確認できる、whole変数の値で、この値をプロセス(thread)のまとまりで合計とってるっぽいのですが、forkとかで子プロセスとか持った場合、親のプロセスを見ると、下のプロセスの統計も加算されてくるのでしょうか?
こんな感じ、PID=16907の情報
ugui7 ~ # cat /proc/16907/io rchar: 9651817 wchar: 10643512 syscr: 1781138 syscw: 1321495 read_bytes: 1109835776 write_bytes: 2892156928 cancelled_write_bytes: 0
使い方
余計なことばかりで、アレなんですが
Total DISK READ : 0.00 B/s | Total DISK WRITE : 686.88 K/s Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 17060 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.27 % [kworker/2:0] 31094 be/4 root 0.00 B/s 400.35 K/s 0.00 % 0.00 % python2.7 -b /usr/lib/python-exec/python2.7/emerge dev-texlive/texlive-latex dev-texlive/texlive-fontutils app-text/texliveこんな感じで、読み書きが多いプロセスを一番上に出力してくれる、他にもユーザーや、PIDで絞れるオプションがあるので確認して見てください。
どうでもいいですね...