iflag=fullblock이 없는 Cat | dd 파이프로 인해 부분 읽기가 발생하는데 왜 128KiB로 잘리나요?

iflag=fullblock이 없는 Cat | dd 파이프로 인해 부분 읽기가 발생하는데 왜 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블록당 128KiB 이상을 읽을 수 없습니다.ddiflag=fullblock

$ 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.html65536바이트로 설정된 것 같습니다.

$ mkfifo /tmp/testfifo
$ python2
>>> fifo_fd = open('/tmp/testfifo', 'rb+')
>>> import fcntl
>>> fcntl.fcntl(fifo_fd, 1032)
65536

(Python3에서는 작동하지 못했습니다.https://bugs.python.org/issue20074)

주요 질문은 (순수한 호기심)입니다. 왜 읽기가 128KiB로 잘리나요?

(아치 리눅스, 커널 5.4.2, zsh 5.7.1에서 테스트되었습니다.)

답변1

이보다 큰 블록 크기 PIPE_BUF(최신 UNIX에서는 5k, Linux에서는 4k)는 조각화 없이 파이프를 통과할 수 없습니다.

이는 다음을 의미합니다.가능한분할되어 있지만 어떤 분할에도 자금이 지원되지 않습니다.

더 많은 것을 읽을 수 있는지 여부는 PIPE_BUF커널의 메모리 상태에 따라 달라집니다. 커널은 모든 커널 메모리를 차지하지 않도록 커널이 쓰기 측을 중지하는 시기를 제어합니다. 또한 읽기 측의 타이밍과 스케줄링, 그리고 충분한 양의 데이터가 축적된 후 깨어나는지 여부에 따라 달라집니다.

참고: dd명명된 옵션은 iflag=fullblock공급업체별 확장입니다. 비표준이므로 사용하지 마십시오.

또한 사용된 쓰기 블록 크기 gcat는 128k인 반면 UNIX 버전 cat은 .mmap()8Mbyte

관련 정보