我一直在深入研究 Linux 内核。想要跟踪 io 请求并准确找出哪个进程发送了当前 io 请求?
有一个名为 current 的结构,内核文档说它代表当前进程。
然而分析打印kblock/blk-core.c 中的函数提交简历看来这不是当前的过程。
我的打印k这是:
printk(" Ata: in block/blk-core.c in submit_bio current task: %s pid:(%d): %s block %Lu on device %s (%u sectors)\n",
current->comm, task_pid_nr(current),
(rw & WRITE) ? "WRITE" : "READ",
(unsigned long long)bio->bi_iter.bi_sector,
bdevname(bio->bi_bdev, b),
count);
然而它的输出并不是我所期望的:
[Thu Dec 31 15:18:49 2015] Ata: in block/blk-core.c in submit_bio current task: jbd2/sda1-8 pid:(494): WRITE block 54798672 on device sda1 (8 sectors)
输出表明当前进程是杰巴德2。根据这个答案 杰巴德2是文件系统运行的函数。与此相反,我的过程是DDPID:2479。
如何准确找到当前 io 请求是哪个进程发送的?就像是奥托普是在做。
答案1
磁盘 I/O 请求通常无法追溯到特定进程。例如,如果两个进程同时访问同一个文件(即进程 1 发出请求,进程 2 在处理进程 1 的请求之前发出加载同一文件的请求),则需要跟踪该访问回到这两个过程。对于延迟写入,写入可能是由于不再存在的进程造成的。
iotop 显示每个进程的 I/O文件级别,而不是磁盘级别。如果您正在查看文件系统驱动程序,current
则会指定发出请求的进程。但是您正在查看块设备驱动程序;除非进程直接访问磁盘(绕过任何文件系统),否则 I/O 请求将来自内部子系统。这就是为什么iotop 的每个进程的统计数据与总数不匹配:总计针对磁盘级别。
正如我们在上面看到的,一般来说,将磁盘 I/O 请求追溯到导致该请求的进程是不可能的。我不知道是否有调试模式允许在可能的情况下进行这种跟踪;我预计它会非常消耗资源。