간결한 버전:어떤 상황에서 데이터를 복사하는 데 안전하게 사용할 수 있습니까 dd
? 즉, 부분적인 읽기 또는 쓰기로 인한 손상 위험이 없다는 의미입니까?
긴 버전 - 서문: dd
일반적으로 특히 장치에서 또는 장치로 데이터를 복사하는 데 사용됩니다(예). 때때로 다른 도구보다 장치의 신비한 속성에 대한 낮은 수준의 액세스 권한 을 갖는 것으로 간주되지만(실제로는 마법을 수행하는 장치 파일입니다) dd if=/dev/sda
때로는 cat /dev/sda
.dd
cat
실전에서는 이길 수 있다. 그럼에도 불구하고,dd
고유한 특성을 가지며 때로는 유용합니다..
질문: dd if=foo of=bar
사실 cat <foo >bar
. 대부분의 unice1에서는 dd
한 번만 호출하면 됩니다.read()
. (제가 찾아보니POSIX"읽기 입력 블록"의 구성이 흐릿합니다 dd
. ) read()
부분 결과가 반환되면(구현 문서에 달리 명시되지 않는 한 POSIX 및 기타 참조 문서에 따라 허용됨) 부분 블록이 복사됩니다. 정확히 같은 문제가 존재합니다 write()
.
관찰 결과: 실제로 블록 장치와 일반 파일을 모두 처리하는 것으로 나타났습니다 dd
. 그러나 이는 실제로 사용해본 경험이 많지 않았기 때문일 수도 있습니다. 파이프라인을 사용하면 dd
오류를 찾는 것이 어렵지 않습니다. 예를 들어이 코드:
yes | dd of=out bs=1024k count=10
그리고 파일 크기를 확인하세요 out
(아마도 10MB 미만일 것입니다).
질문dd
: 어떤 상황에서 데이터 복사에 안전하게 사용할 수 있나요 ? 즉, 블록 크기, 구현, 파일 유형 등의 어떤 조건이 dd
모든 데이터가 복사되도록 보장합니까?
(GNU dd완전한 청크를 전송하기 위해 호출 하거나 루프 fullblock
하도록 지시하는 플래그가 있습니다 . 그러니 항상 안전해요. 내 질문은 이러한 플래그가 사용되지 않는 경우(다른 구현에는 존재하지 않는 경우)에 관한 것입니다. )read()
write()
dd iflag=fullblock
1OpenBSD , GNU coreutils, BusyBox를 확인했습니다.
답변1
~에서사양:
- 만약에
bs=
expr
피연산자가 지정되고sync
,noerror
또는 이외의 변환이 요청되지 않은 경우 각 입력 블록에서 반환된 데이터는 전체 블록보다 적고 변환이 지정되지 않은notrunc
경우 별도의 출력 블록에 기록됩니다. 입력 청크의 크기는 동일합니다.read()
sync
그래서 그것이 아마도 당신의 혼란을 일으키는 원인일 것입니다. 응, 그렇기 dd
때문에디자인됨차단의 경우 부분 s는 기본적으로 read()
부분 s에 1:1로 매핑됩니다. 그렇지 않으면 write()
지정 시 sync
후행 NUL 또는 공백 문자가 크기에 맞게 채워집니다 bs=
.conv=sync
이는 dd
다음을 의미합니다.데이터 복사에 안전함(부분 읽기 또는 쓰기로 인한 손상 위험 없음)매개변수에 의해 임의로 제한되는 경우를 제외하고 모든 경우에 입력 이 완전히 전달될 때까지 입력과 동일한 크기의 청크로 출력 됩니다 count=
. 이 경고조차dd
write()
read()
read()
유일한 진짜bs=
지정된 경우 obs=
또는아니요사양의 다음 문장에 명시된 대로 지정됩니다.
- 만약에
bs=
expr
sync
피연산자가 지정되지 않았거나 ,noerror
또는 이외의 변환이 요청된 경우notrunc
입력을 처리해야 합니다.전체 크기 출력 블록으로 수집입력이 끝날 때까지.
ibs=
및/또는 매개변수가 없으면 이는 중요하지 않습니다. obs=
기본적으로 ibs
및 의 크기가 동일하기 때문입니다 obs
. 그러나 당신은분명히 있을 수 있다입력 버퍼링과 관련하여 다음을 지정하십시오.다른 크기어떤 금액이든아니요지정하다bs=
(우선순위이기 때문에).
예를 들어, 다음과 같은 경우:
IN| dd ibs=1| OUT
...그러면 POSIX는 512바이트 단위가 됩니다 dd
.write()
모으다각 read()
바이트를 단일 출력 블록에 넣습니다.
그렇지 않으면 만약 당신이...
IN| dd obs=1kx1k| OUT
...POSIX dd
는read()
최고한 번에 512바이트이지만 write()
각 메가바이트 크기의 출력 블록(커널은 마지막 가능한 것을 허용하고 제외합니다 - 그것이 EOF이기 때문입니다)입력을 수집하여 완전히풀 사이즈 출력 블록.
그러나 사양에서도 다음과 같습니다.
count=n
- 복사만 가능N입력 블록.
count=
블록 에 매핑되므로 이식성에 대한 임의의 제한을 i?bs=
처리하려면 count=
두 개의 가 필요합니다 dd
. 두 개의 s로 이를 수행하는 가장 실용적인 방법 dd
은 하나의 출력을 다른 하나의 입력으로 파이프하는 것입니다. 이는 확실히 우리가 읽기 영역에 들어가게 합니다. /쓰기 ㄱ.특수 파일원래 입력 유형에 관계없이.
IPC 파이프는 args를 지정할 때 [io]bs=
안전하게 수행하려면 값이 시스템 정의 PIPE_BUF
제한 내에서 유지되어야 함을 의미합니다. POSIX는 시스템 커널이 원자 s와 s가 read()
정의된 write()
범위 내에 있다는 것만 보장해야 한다고 규정합니다.PIPE_BUF
limits.h
. PIPE_BUF
POSIX 보증적어도...
{_POSIX_PIPE_BUF}
- 파이프에 쓸 때 원자성을 보장하는 최대 바이트 수입니다.
- 값: 512
...dd
(이것은 기본 I/O 블록 크기 이기도 합니다 .)이지만 실제 값은 일반적으로 최소 4k입니다. 최신 Linux 시스템에서는 기본적으로 64k입니다.
따라서 프로세스를 설정할 때는 dd
블록에서 수행해야 합니다.요인세 가지 가치를 기반으로 합니다.
- bs = (obs =
PIPE_BUF
이하) - n = 읽을 총 바이트 수
- 개수 = n/BS
좋다:
yes | dd obs=1k | dd bs=1k count=10k of=/dev/null
10240+0 records in
10240+0 records out
10485760 bytes (10 MB) copied, 0.1143 s, 91.7 MB/s
dd
검색할 수 없는 입력을 처리하려면 i/ow/를 동기화해야 합니다 . 즉, 파이프 버퍼를 명시적으로 만들면 더 이상 문제가 되지 않습니다. 그것이 dd
목적입니다. 여기서 알 수 없는 수량은 yes
버퍼 크기입니다. 하지만 다음과 같이 차단하면모두 다 아는다른 수량을 사용 dd
하고 약간의 곱셈을 하면dd
데이터 복사에 안전함(부분 읽기 또는 쓰기로 인한 손상 위험 없음)모든 POSIX 시스템 에서도 count=
임의의 입력 유형으로 입력을 임의로 제한하고 단일 바이트를 잃지 않습니다.
이것은에서 온 것입니다POSIX 사양:
ibs=
expr
- 입력 블록 크기를 바이트 단위로 지정합니다.
expr
(기본값은 512입니다).
- 입력 블록 크기를 바이트 단위로 지정합니다.
obs=
expr
- 출력 블록 크기를 바이트 단위로 지정
expr
(기본값은 512입니다).
- 출력 블록 크기를 바이트 단위로 지정
bs=
expr
- 입력 및 출력 블록 크기를 다음으로 설정합니다.
expr
, ,ibs=
및obs=
이외의 변환이 지정되지 않은 경우 각 입력 블록은 짧은 블록을 집계하지 않고 단일 블록으로 출력에 복사되어야 합니다.sync
noerror
notrunc
- 입력 및 출력 블록 크기를 다음으로 설정합니다.
또한 이들 중 일부는 더 잘 설명되어 있음을 알게 될 것입니다.여기.
답변2
소켓, 파이프 또는 tty의 경우 read() 및 write()는 요청된 크기보다 적게 전송할 수 있으므로 이에 대해 dd를 사용할 때 fullblock 플래그가 필요합니다. 그러나 일반 파일 및 블록 장치의 경우 간단한 읽기/쓰기가 가능한 경우는 EOF에 도달한 경우 또는 오류가 발생한 경우의 두 번뿐입니다. 이것이 바로 fullblock 플래그가 없는 이전 dd 구현을 디스크 복사에 안전하게 사용할 수 있는 이유입니다.