根据限制文件 IO 速度,我构建了https://git.data.coop/tange/tangetools/src/branch/master/iothrottle
它适用于某些程序:
iothrottle -i 10M cat foo > bar # Yes, here you could just use pv
iothrottle -o 1M ffmpeg -i foo.mp3 foo.wav
iothrottle -o 1M cp -a foodir /other/fs/foodir
这不会:
iothrottle -o 1M cp -a foodir /same/fs/foodir
因为在同一个文件系统上每个文件cp
使用一次调用copy_file_range
。
我可以接受这个限制。
它对 也不起作用seq
。当我运行时,strace seq 100000
我得到:
write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
write(1, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 4096) = 4096
write(1, "2680\n2681\n2682\n2683\n2684\n2685\n26"..., 4096) = 4096
write(1, "499\n3500\n3501\n3502\n3503\n3504\n350"..., 4096) = 4096
write(1, "18\n4319\n4320\n4321\n4322\n4323\n4324"..., 4096) = 4096
write(1, "7\n5138\n5139\n5140\n5141\n5142\n5143\n"..., 4096) = 4096
write(1, "\n5957\n5958\n5959\n5960\n5961\n5962\n5"..., 4096) = 4096
write(1, "6776\n6777\n6778\n6779\n6780\n6781\n67"..., 4096) = 4096
write(1, "595\n7596\n7597\n7598\n7599\n7600\n760"..., 4096) = 4096
write(1, "14\n8415\n8416\n8417\n8418\n8419\n8420"..., 4096) = 4096
write(1, "3\n9234\n9235\n9236\n9237\n9238\n9239\n"..., 3838) = 3838
因此它似乎在调用write
(而不是某些mmap
或其他魔法),因此应该起作用。
但是当我运行时:IOTHROTTLE_DEBUG=1 iothrottle -o 1M seq 10000 >/dev/null
我得到:
init called: default read_limit=0, write_limit=0
IOTHROTTLE_READ=0
IOTHROTTLE_WRITE=1048576
Final read_limit=0, write_limit=1048576
allowed: 608 written: 0
allowed: 617 written: 0
这告诉我iothrottle
仅拦截了 2 次调用write
。
我错过了什么?
您
iothrottle
可以通过劫持 C 库的函数来完成工作,这些函数最终会执行诸如write()
、pwrite()
或splice()
² 之类的系统调用。strace
跟踪系统调用,而不是动态库函数调用,ltrace
在 GNU 系统上您需要动态库函数调用(ltrace
也可以使用 跟踪系统调用-S
;在其他系统上,等效命令如truss
或tusc
(HP/UX)也可以同时执行这两项操作)。以下是来自
zsh
Debian 的内容:seq
正在调用fwrite_unlocked()
您未劫持的 stdio 函数,fwrite()
这不能解释为什么您的iothrottle
操作对其无效。显示一些需要的
-u
未定义的-D
动态符号seq
(=seq
可以在其他 shell 中写入"$(command -v seq)"
)。在动态符号的环境中调用
seq
,LD_DEBUG=bindings
显示关于在哪里为谁找到什么符号的信息,这也可以有所帮助:¹ 或者可能最终像 stdio 那样,通常只填满一些缓冲区而不执行任何 I/O,直到这些缓冲区被刷新。
² 顺便说一句,还有更多诸如
send()
、、之类的函数也可以执行一些 I/O 操作sendto()
,并且sendmsg()
还有更多 stdio 函数可以执行一些操作,write()
例如fput()
、、......putchar()
printf()