단지 장치의 작은 부분을 0이나 임의의 비트로 덮고 싶을 뿐입니다. 보다 정확하게는 모든 섹터의 처음 1% 또는 몇 MiB를 다루고 싶습니다. 이를 수행하는 쉬운 방법이 있습니까?
답변1
매우 느리기 때문에 /dev/urandom
많은 양의 데이터(전체 디스크)를 처리하는 데는 적합하지 않지만 작은 영역에는 적합할 수 있습니다.
8MiB를 다루는 예:
dd bs=1M count=8 iflag=fullblock if=/dev/urandom of=/dev/destroyme
또는 다음을 사용할 수 있습니다 shred
.
shred -v -n 1 -s 8M /dev/destroyme
또한 losetup
특정 크기 및 오프셋의 장치를 생성하고 자체 크기/오프셋 옵션이 없는 유틸리티를 사용하여 이를 재정의할 수도 있습니다.
losetup --find --show --offset 0 --sizelimit $((8*1024*1024)) /dev/destroyme
# will print /dev/loopX
cat /dev/urandom > /dev/loopX
losetup -d /dev/loopX
답변2
다른 파일과 마찬가지로 처음 10MiB를 0으로 덮어씁니다.
head -c10M < /dev/zero 1<> /dev/sdax
블록 장치 파일의 경우 1<>
잘림 없이 열 필요조차 없습니다. 블록 장치 잘림 같은 것이 없기 때문에 다음과 같이 간단하게 수행할 수 있습니다.
head -c10M < /dev/zero > /dev/sdax
모든 헤더 구현이 이것을 지원하는 것은 아니며 -c
, 지원하는 경우 모두가 이 M
접미사를 지원하는 것은 아닙니다(지원하는 경우 내장 에서처럼 M
메가바이트(1000000바이트) 또는 GNU에서처럼 메가바이트(1048576바이트)를 의미할 수 있습니다 ). 이 경우 다음을 수행할 수 있습니다.ksh93
head
head
head -c "$((10 * 1024 * 1024)"
확실히 해.
비교해보면 dd bs=1M count=10 < /dev/zero > /dev/sdax
:
개념적으로
head
파일에서 지정된 수의 바이트 또는 라인을 읽고 이를 stdout에 쓰는 명령입니다.- while은
dd
원하는 방식으로 데이터를 읽고 쓸 수 있는 하위 수준 명령입니다.
head
작업을 위해 설계된 명령이기 때문에 여기서 사용하고 있습니다 .dd
특정 사용 사례에 맞게 최적화하거나 특정 기능 중 하나를 사용하려는 경우dd
이를 사용합니다 (이식성에 대한 참고 사항도 참조).읽기 + 쓰기 루프:
head -c10M
관계없이 요청된 데이터를 읽으려는 시도가 이루어지며 오류가 발생한 경우 종료 상태가 0이 아닌 경우에만 실패합니다.dd bs=1M count=10
, 10번의 읽기가 수행되며(오류가 없는 한), 일부 데이터를 반환하는 읽기마다 읽은 데이터 양을 사용하여 해당 쓰기가 수행됩니다. 이 방법은 각 읽기가 요청된 데이터 1M를 정확히 반환하는 경우에만 작동합니다. 실제로는 맞습니다/dev/zero
. 하지만 Linux(최소 4.6)에서는/dev/urandom
한 번의 읽기로 32MiB에서 1바이트의 데이터를 뺀 것 이상을 얻을 수 없습니다(따라서 1MiB의 경우에는 여전히 괜찮지만 다른 버전인 Linux용 YMMV를 사용하는 경우). , 그리고 의 경우에는/dev/random
몇 바이트(현재 엔트로피 풀에 있는 바이트)만 있습니다. GNU 구현에는 요청 버퍼가 가득 찰 때까지 계속 읽는 동작이dd
있지만 GNU가 없는 경우 유일한 옵션은 한 번에 1바이트 읽기를 수행하는 것인데 이는 성능에 큰 영향을 미칩니다.iflag=fullblock
head
dd
성능: 소량의 데이터(수백 메가바이트 미만)(데이터가 나중에 디스크에 플러시되거나 기록될 버퍼에 기록되는 경우) 이외의 모든 경우
/dev/null
프로세스는 I/O 바인딩됩니다. 읽기/dev/urandom
또는/dev/random
병목 현상이 발생하는 경우 난수 생성 또는 디스크 I/O가 발생합니다. 이 경우 dd와 head 사이에는 큰 차이가 없습니다. 어떤 경우든head
CPU 오버헤드가 더 높을 가능성이 있습니다(성능이 I/O 바인딩된 경우에는 알 수 없음).head
기본적인 도구이다. 구현은 모든 유형의 입력 및 출력에 대해 여전히 안정적이고 너무 많은 리소스를 사용하지 않으면서 가능한 한 효율적으로 작업을 수행하려고 노력합니다. 동일한 읽기+쓰기 루프를 수행합니다dd
. 성능의 주요 차이점은 읽기 및 쓰기 크기이며, 이에 따라 수행된 시스템 호출 수가 결정됩니다.이러한 크기는 시스템 구현 및 버전에 따라 다르며
head
시스템에 따라 달라질 수 있습니다. 내 시스템에서 최신 버전의 GNU를 사용할 때head
읽기 크기는 BUFSIZE(GNU 시스템에서는 8KiB)이고 쓰기 크기는 4KiB이지만 변경할 수 있습니다stdbuf -o 1M
.ksh93
내장head
함수는 64KiB 읽기 및 쓰기를 수행하고 적어도 내 시스템에서는 libc의 stdio를 사용하지 않는 것으로 보입니다.GNU의
head
stdio 사용은 stdio가 추가 오버헤드를 발생시킨다는 것을 의미합니다(구현은 시스템에 따라 다름).현재 버전의 GNU는 캐시가 그에 따라 최적화될 수 있도록 데이터를 순차적으로 읽을 것임을 시스템에 알리는
cat
데 사용됩니다 .fadvise
일부 구현이head
이 작업을 수행할 수 있거나 미래에도 수행할 수 있다는 것은 불가능하지 않습니다. 낮은 수준이기 때문에 사용자가 지시한 경우에만 실행되기를 원합니다( 이러한 지원이 있는 구현dd
은 알지 못합니다 ).dd
dd
read()
매우 낮은 수준으로 직접 호출 및write()
시스템 호출을 수행합니다 . Linux와 같은 특수 API를 사용하는 것 외에는 이보다 훨씬 더 효율적일 수 없습니다sendfile()
.read()
이를 통해 합계 크기를 더 잘 제어할 수write()
있으므로 입력/출력 유형과 사용 가능한 리소스를 기반으로 최적화할 수 있습니다. 예를 들어 여유 메모리가 많다면 한 번에 전체 데이터를 읽는 것이 나을 것입니다. (비록 제가 테스트해 본 결과 /dev/zero에서 /dev로 복사할 때 과거에 비해 크게 개선된 점은 보이지 않았습니다. /null) 크기는 32KiB이며, 블록 크기가 1MiB 이후에도 성능이 떨어지기 시작합니다.
이식성
-c
,bs=10M
, 은(는)conv=fullblock
이식 가능하지 않습니다. 파일에서 특정 양의 데이터를 읽는 유일한 POSIX 명령은 이지만dd
, 이를 안정적으로 사용하려면( on 제외/dev/zero
) 위에서 언급한 대로bs=1
성능이 좋지 않습니다.쓰기 오류의 결과.
블록 장치의 끝을 지나서 쓰려고 하면
head
둘 다 즉시 종료됩니다 .dd
디스크에 결함이 있는 섹터가 있는 경우 디스크에 대한 실제 쓰기가 비동기식이므로 일반적으로 감지되지 않습니다. GNU 구현을 사용하면dd
직접 쓰기를 강제할 수 있습니다.oflag=direct
이는dd
첫 번째 오류에서 중지하는 것을 의미합니다. 첫 번째 실패한 섹터 이전에 최대한 많은 데이터를 쓰려면 기본 블록 크기인 512를 사용할 수 있습니다.읽기 오류의 결과
/dev/zero, /dev/urandom 또는 /dev/random에서 읽기 오류가 발생하면 안 됩니다. 그러나 더 일반적으로는 첫 번째 읽기에서
head
및 둘 다dd
오류와 함께 종료됩니다. 를 사용하면dd
계속 오류를 사용할 수 있습니다conv=noerror
. 이 경우 실패한 블록을 0으로 채우는 옵션sync
( ) 을 추가할 수 있습니다 . 이는 해당 기능을 위해 설계되지 않았기 때문에 이를 수행할 수 있는 옵션을 제공하지 않습니다.conv=noerror,sync
head
대안.
pv -Ss 10M < /dev/zero > /dev/sdax
10M을 복사하고 진행률 표시줄을 표시합니다. 테스트에서 기본 읽기/쓰기 크기는 128KiB였습니다. options 을 사용하여 이를 변경할 수 있지만-B
내 테스트에서는 128KiB가 최상의 결과를 제공했습니다. s 와 동일한 옵션이pv
있습니다 .-E
dd
conv=noerror,sync
Linux에서는 성능을 최적화하기 위해 시스템 호출을 사용하므로 파이프를 통한 I/O도 용이하게 합니다
splice()
.시스템 호출을 사용하려면 를
sendfile()
사용할 수 있습니다xfs_io
.xfs_io -c 'sendfile -i src 0 10M' dst
src에서 dst로 10M 데이터를 보냅니다. 그러나 그것은 단지하나
sendfile()
/dev/zero
그리고 ,/dev/random
또는 에서는 시스템 호출을 사용할 수 없습니다/dev/urandom
. 그러나 스파스 파일에는 사용할 수 있습니다.truncate -s 1T empty-file xfs_io -c 'sendfile -i empty-file 0 10M' /dev/sdax
작동할 수 있지만 대용량(수 기가바이트)의 경우 이는
sendfile()
시스템 호출이기 때문에 그만큼의 메모리를 할당해야 하므로 효율성이 떨어집니다 . 이상적으로 는 몇 기가바이트 이상을 수행하고dd bs=1M
싶습니다 .sendfile()
시간 바이트 조작을 수행할 수 있지만 이를 수행할 수 있는 명령은 없습니다.입력을 위해
/dev/zero
실제로는 필요하지 않습니다.읽다당신이 쓰는 각 블록에 대한 데이터. 결국 그것은 단지 0입니다. 를 읽지 않고 0만 있는 버퍼를 만드는 것은 쉽고/dev/zero
, 각 쓰기 사이에 이를 재사용할 수 있습니다. 예를 들어:PERLIO=:unix perl -e '$x = pack("x" . 1024*1024); print $x for 1..10000' > /dev/sdax
perl
10000MiB를 쓰는 것은 반복적인 읽기 솔루션보다 더 효율적입니다(오버헤드에도 불구하고) /dev/zero
.
답변3
당신은 임의의 데이터를 제공하는 장치를 사용하여 dd
이를 수행 할 수 있습니다. /dev/urandom
한 가지 예:
dd if=/dev/urandom of=/dev/sdX bs=1M count=100
이렇게 하면 100MB의 임의 데이터가 기록됩니다.
if
입력 파일입니다of
출력 파일입니다bs=1M
블록 크기는 1Mbyte입니다.count
이 블록은 몇 번이나 작성되어야 합니까?
/dev/zero
입력 파일 이나 /dev/null
데이터를 제공하는 다른 파일을 사용할 수도 있습니다 . 이 명령은 출력 파일/장치의 시작 부분에서 데이터 쓰기를 시작합니다.