빈 원시 블록 장치에 파일을 쓸 때마다.
# dd if=image.iso of=/dev/sdb status=progress
저는 어떤 유형도 사용해 본 적이 없습니다 sync
(예: sync
;;;;).conv=fsync
conv=fdatasync
oflag=sync
oflag=dsync
나는 이것이 dd
아니라는 것을 알았습니다.한 번모든 쓰기가 완료될 때까지 종료합니다.
나는 항상 Conky의 I/O 도구를 사용하며 grep Dirty /proc/meminfo
, 또한 장치의 체크섬은 항상 해당 장치에 작성된 파일의 체크섬과 일치합니다. 따라서 저는 항상 전체 파일이 장치에 기록되었다고 100% 확신합니다.
비교를 위해 파일을 ext4 볼륨에 기록했습니다. 예를 들어 다음을 사용합니다.
$ dd if=/dev/urandom of=~/file bs=1M count=50 iflag=fullblock
ext4 볼륨에 쓸 때 dd
데이터가 실제로 디스크에 기록되기 전에 종료 후 항상 약 20초의 지연이 있습니다.
많은 사람들은 블록 장치에 쓸 때 명령 다음에 이 명령을 사용하거나 sync
명령에 dd
여러 옵션 중 하나를 포함하는 것을 옹호합니다. 예를 들어sync
dd
여기그리고여기. 그러나 나는 이것이 필요하다는 것을 실제로 증명한 사람을 아직 알지 못합니다.
댓글 중 하나는이 페이지예:
sync
여기서는 의미가 없습니다 [즉, 직접 작성/dev/sdX
]. 파일 시스템 작업에만 영향을 미칩니다.
5명이 이 리뷰에 동의했는데, 이는 내 경험과 일치합니다.
dd
그러면 블록 장치에 쓸 때 모든 쓰기가 완전히 완료되기 전에 종료되는 상황이 있습니까 ? 이런 일이 정말 누구에게나 일어날까요?
및 와 같은 다른 쓰기 옵션은 cp
어떻습니까 cat
? 블록 장치에 쓰기가 완료되기 전에 종료할 수 있습니까?
답변1
이제 이 질문에 답할 시간입니다.
오랫동안 나는 블록 장치가 아닌 파일 시스템에 대한 쓰기만 캐시된다고 생각했는데, 알고 보니 내 생각이 틀렸습니다.블록 장치에 대한 쓰기는 캐시됩니다..
기술적으로 말하면 나는공식적인출처를 밝히고 답변을 받으면 업데이트하겠습니다., 그러나 여기에서 몇 가지 정보를 찾을 수 있습니다.linux - 블록 장치 캐시 및 파일 시스템. 죄송합니다. 귀하도 이 질문을 보신 것으로 확인되었습니다.
실제로 이미지를 USB 스틱에 추가한 다음 작업이 완료되면 꺼내는 데 문제가 발생했는데 이미지가 손상되었음을 발견했습니다. 전체 동기화가 장치에서 마지막으로 완료된 것처럼 보이기 때문에 이렇게 작동해서는 안 됩니다 close()
. 따라서 장치에 데이터가 손상되었거나 아직 블록 장치가 열려 있는 프로세스가 누락된 것 같습니다. 하지만 어느 쪽이든 더 이상 모험을 하지 마세요.
그렇습니다. 블록 장치에 쓸 때 동기화 옵션을 추가하는 것은 dd
도시 전설이 아닌 것 같습니다. 나는 conv=fdatasync
이것이 충분하고 최상의 성능을 발휘해야 한다고 생각합니다(결국 파일 메타데이터는 추가되지 않으며 프로세스가 끝날 때만 동기화하면 됩니다). 그러나 우리 중 극단주의자들은 oflag=sync
(모든 쓰기 후 전체 데이터 + 메타데이터 동기화)를 선호할 수도 있습니다. 확인해보시고 man 2 open
더 man 2 fdatasync
많은 인사이트를 얻으세요.
내가 읽은 바에 따르면(불행히도 아직 공식적인 내용은 없음) 장치가 시작될 때 일부 SYNC 플래그를 사용하여 명시적으로 요청 하지 않는 한 다른 프로세스 cp
가 아직 열려 있으면 블록 장치는 동기화하기 전에 실제로 종료될 수 있습니다 . 예 , 또는 더 과장되게 말하면 이러한 명령 중 어느 것도 없습니다 ...cat
open()
fdatasync()
fsync()
sync()
답변2
그래서 저는 그런 것을 테스트해왔고 그것이 우리에게 알려주는 것은 dd 프로세스의 스택 추적입니다.
나는 상태=진행을 포함하여 블록 장치를 직접 추가했습니다(페이지 캐시를 우회하는 oflag=direct가 없음). 그리고 내가 얻은 것은 다음과 같습니다. 상태는 매우 빠른 187MB/s를 표시합니다(페이지 캐시를 우회하는 양만큼). 쓰기 시간) 페이지 캐시는 작습니다. 그러나 dd는 블록 장치에서 blkdev_close를 호출한 다음 기다리고, 완료되면 쓰기에 필요한 총 시간을 기준으로 속도가 훨씬 느려집니다(닫기 시 플러시 포함). 부르다).
echo;echo;echo;date; dd if=/dev/urandom bs=1M of=/dev/mockdevice status=progress; date
Thu 08 Oct 2020 10:47:36 AM EDT
3172990976 bytes (3.2 GB, 3.0 GiB) copied, 17 s, 187 MB/s
dd: error writing '/dev/mockdevice': No space left on device
3073+0 records in
3072+0 records out
3221225472 bytes (3.2 GB, 3.0 GiB) copied, 1681.94 s, 1.9 MB/s
Thu 08 Oct 2020 11:15:38 AM EDT
dd 완료 후 플러시할 때의 스택 추적은 다음과 같습니다(제 경우에는 디스크가 꽉 찼을 때 오류가 발생했습니다).
cat /proc/1130961/stack
[<0>] __lock_page+0x128/0x230
[<0>] write_cache_pages+0x354/0x4b0
[<0>] generic_writepages+0x57/0x90
[<0>] blkdev_writepages+0xe/0x10
[<0>] do_writepages+0x43/0xd0
[<0>] __filemap_fdatawrite_range+0xd5/0x110
[<0>] filemap_write_and_wait+0x44/0xa0
[<0>] __blkdev_put+0x72/0x1e0
[<0>] blkdev_put+0x4e/0xe0
[<0>] blkdev_close+0x26/0x30
[<0>] __fput+0xcc/0x260
[<0>] ____fput+0xe/0x10
[<0>] task_work_run+0x8f/0xb0
[<0>] exit_to_usermode_loop+0x131/0x160
[<0>] do_syscall_64+0x163/0x190
[<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
dd를 사용하여 페이지 캐시를 채우면 페이지 캐시가 한 번에 한 페이지씩 블록 장치로 플러시된다는 점도 주목할 가치가 있습니다. 파일 시스템은 Bio를 플러시하기 위해 많은 수의 페이지가 포함된 BIOS를 전송하지만 위 스택 추적의 페이지 캐시 플러셔는 Bio당 한 페이지만 푸시하는 것으로 나타납니다.
따라서 내 경험상 blkdev_close는 반환하고 dd가 완료되도록 하기 전에 실제로 모든 더티 캐시 페이지를 블록 장치로 플러시하기 때문에 sync를 호출할 필요가 없습니다.