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で絞れるオプションがあるので確認して見てください。
どうでもいいですね...