为什么在 /proc/[PID]/io 中忽略了 memmap IO

Kiw*_*iwy 3 memory io proc

我有一个问题 /proc/[PID]/io 和 memmap 我需要分析使用 python 库astropy 的应用程序 IO 。
我遇到的问题之一是 /proc/[PID]/io.io 中的 IO 读/写总字节数不正确。

我有一个脚本copy.sh

#!/bin/bash
cp huge.fits huge.2.fits
#python copyfits.py
#python copyfitsMemmapOFF.py
sleep 5 
cat /proc/$$/io
Run Code Online (Sandbox Code Playgroud)

我注释了cp要为每个测试运行的行和行。

copyfits.py 包含:

from astropy.io import fits    
hdulist = fits.open('huge.fits', mode='readonly')
hdulist.writeto('huge.2.fits')
hdulist.close()
Run Code Online (Sandbox Code Playgroud)

copyfitsMemmapOFF.py 包含:

    from astropy.io import fits    
    hdulist = fits.open('huge.fits', mode='readonly', memmap=False)
    hdulist.writeto('huge.2.fits')
    hdulist.close()
Run Code Online (Sandbox Code Playgroud)

下面是每个解决方案的 IO 结果:

cp huge.fits huge.2.fits

rchar: 9749929202
wchar: 9749551680
Run Code Online (Sandbox Code Playgroud)

python copyfits.py

**rchar: 8399421**
wchar: 9749551685
Run Code Online (Sandbox Code Playgroud)

python copyfitsMemmapOFF.py

rchar: 9757502959
wchar: 9749551685
Run Code Online (Sandbox Code Playgroud)

我知道当使用这个变量来监控应用程序读取文件的数量时,关闭 memmap 会导致不一致的 IO 结果。如何/为什么 memmap 不计入标准 IO,我如何知道这些 IO ?
因为如果它是内核而不是应用程序读取文件,该文件仍然被访问。

Ste*_*itt 6

/procio只跟踪‘明确的’I / O,I /使用少量的系统调用Ø执行。对于读取,那些是readreadvpreadvsendfile,和copy_file_range; 您可以看到使用add_rcharin累积的统计数据fs/read_write.c

内存映射文件的 I/O 完全不同;读取时,它依赖于页面错误处理,并进行了许多优化以提高性能(预读等)。您可以通过查看/proc/${pid}/stat(字段 10 和 12)中的页面错误在一定程度上对其进行跟踪。困难的部分是计算每个页面错误读取了多少数据;我的实验表明每个故障 64KiB,但我还没有找到支持它的硬数据(这可能取决于具体情况)。

从进程的角度来看,我不知道有任何现成的跟踪映射 I/O 的方法(读取到进程中的字节,无论是否实际发生了任何块 I/O)。

准确计算内存映射读取被证明是一个相当棘手的问题,主要是因为会计必须反映意图的方式。io计算程序明确要求读取或写入的字节数;但是当一个进程将一个文件映射到它的内存时,读取的粒度由内核决定,而不是读取进程。你每 4KiB 只能读取一个字节,内核会为你读取整个文件——记账应该反映什么?它不能轻易反映进程在内存中真正读取的字节数,这会对性能产生巨大影响(而且不可能在所有架构中实现)。