Pipe
貓 |dd 管道導致沒有 iflag=fullblock 的部分讀取,為什麼截斷為 128KiB?
考慮這個範例 1MiB 文件:
$ dd if=/dev/zero of=input.img bs=1M count=1 1+0 records in 1+0 records out 1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00100595 s, 1.0 GB/s
如果我嘗試使用
cat
它並在dd
不使用的情況下將其導入,iflag=fullblock
則每個塊的讀取量不能超過 128KiB:$ cat input.img | dd of=output.img bs=128k count=1 1+0 records in 1+0 records out 131072 bytes (131 kB, 128 KiB) copied, 0.000221117 s, 593 MB/s
$ cat input.img | dd of=output.img bs=129k count=1 0+1 records in 0+1 records out 131072 bytes (131 kB, 128 KiB) copied, 0.000495317 s, 265 MB/s
$ cat input.img | dd of=output.img bs=1M count=1 0+1 records in 0+1 records out 131072 bytes (131 kB, 128 KiB) copied, 0.000437209 s, 300 MB/s
使用 2 個塊計數它甚至會列印一個警告:
$ cat input.img | dd of=output.img bs=129k count=2 dd: warning: partial read (131072 bytes); suggest iflag=fullblock 0+2 records in 0+2 records out 262144 bytes (262 kB, 256 KiB) copied, 0.00107657 s, 243 MB/s
我認為這可能是由於管道緩衝區的大小,但是我在https://www.golinuxhub.com/2018/05/how-to-view-and-increase-default-pipe-size-buffer 之後檢查了它的大小。 html,它似乎設置為 65536 字節:
$ mkfifo /tmp/testfifo $ python2 >>> fifo_fd = open('/tmp/testfifo', 'rb+') >>> import fcntl >>> fcntl.fcntl(fifo_fd, 1032) 65536
(請注意,由於https://bugs.python.org/issue20074,我猜我無法使其與 Python3 一起使用)
主要問題是(純粹的好奇):為什麼讀取被截斷為 128KiB?
(在 Arch Linux、核心 5.4.2、zsh 5.7.1 上測試。)
任何大於
PIPE_BUF
(現代 UNIX 上為 5k,Linux 上為 4k)的塊大小都不允許在沒有碎片的情況下通過管道。這意味著,它可能會被拆分,但沒有拆分的授權。
您是否能夠讀取更多內容
PIPE_BUF
取決於核心的記憶體狀態,該狀態控制核心何時停止寫入端以防止牠吃掉所有核心記憶體。它還取決於讀取端的時序和調度,以及它是否在積累了足夠數量的數據後被喚醒。順便說一句:
dd
名為的選項iflag=fullblock
是供應商特定的擴展。避免使用它,因為它是非標準的。另請注意,
gcat
使用 128k 的寫入塊大小,而 UNIX 版本cat
基於mmap()
並使用8Mbyte
. 因此,如果您確實在遺傳 UNIX 上執行此測試,您可以讀取大於 128k 的塊,