Ze specyfikacji :
- Jeżeli
bs=exprargument jest określony i nie są wymagane żadne konwersje inne niż sync, noerrorlub dane notruncsą wymagane, dane zwrócone z każdego bloku wejściowego zapisuje się jako osobny blok wyjściowy; jeżeli read()zwraca mniej niż pełny blok, a synckonwersja nie jest określona, wynikowy blok wyjściowy ma taki sam rozmiar jak blok wejściowy.
Prawdopodobnie to właśnie powoduje twoje zamieszanie. Tak, ponieważ ddjest przeznaczony do blokowania, domyślnie częściowe read()s zostaną zamapowane 1: 1 na częściowe write(), lub syncd na wypełnieniu ogona NUL lub znakami spacji do bs=rozmiaru, gdy conv=synczostanie określony.
Oznacza to, że ddmożna bezpiecznie używać do kopiowania danych (bez ryzyka uszkodzenia z powodu częściowego odczytu lub zapisu) w każdym przypadku, z wyjątkiem jednego, w którym jest on arbitralnie ograniczony przez count=argument, ponieważ w przeciwnym razie jego dane wyjściowe w blokach o identycznych rozmiarach ddbędą szczęśliwie write()do tych, w których jego wkład był, read()dopóki nie read()przejdzie przez to całkowicie. I nawet to zastrzeżenie jest prawdziwe tylko wtedy, gdy bs=jest określone lub nieobs= jest określone, ponieważ następne zdanie w specyfikacji stwierdza:
- Jeżeli
bs=exprargument nie jest określony lub wymagana jest konwersja inna niż sync, noerrorlub notruncwymagane jest, dane wejściowe będą przetwarzane i gromadzone w pełnowymiarowych blokach wyjściowych, aż do osiągnięcia końca danych wejściowych.
Bez argumentów ibs=i / lub obs=nie ma to znaczenia - ponieważ ibsi obsoba mają domyślnie ten sam rozmiar. Możesz jednak uzyskać wyraźne informacje na temat buforowania danych wejściowych, określając dla nich różne rozmiary i nie określając bs= (ponieważ ma to pierwszeństwo) .
Na przykład, jeśli wykonasz:
IN| dd ibs=1| OUT
... wtedy POSIX ddbędzie write()składał się z 512 bajtów, zbierając każdy pojedynczy read()bajt w pojedynczy blok wyjściowy.
W przeciwnym razie, jeśli zrobisz ...
IN| dd obs=1kx1k| OUT
... POSIX ddbędzie miał jednocześnie read() maksymalnie 512 bajtów, ale write()każdy blok wyjściowy wielkości megabajta (jądro pozwala i może z wyjątkiem ostatniego - ponieważ to jest EOF) w całości, zbierając dane wejściowe do pełnowymiarowych bloków wyjściowych .
Jednak również ze specyfikacji:
count=n
- Kopiuj tylko n bloków wejściowych.
count=mapuje na i?bs=bloki, więc aby poradzić sobie z dowolnym ograniczeniem count=przenośnym, potrzebujesz dwóch dds. Najbardziej praktycznym sposobem na zrobienie tego za pomocą dwóch dds jest podłączenie wyjścia jednego z nich do wejścia drugiego, co z pewnością stawia nas w sferze czytania / pisania specjalnego pliku, niezależnie od pierwotnego typu wejścia.
Rura IPC oznacza, że przy określaniu [io]bs=argumentów, że aby to zrobić bezpiecznie, musisz utrzymać takie wartości w ramach zdefiniowanego PIPE_BUFlimitu systemu. POSIX stwierdza, że jądro systemu musi zagwarantować tylko atomowe read()S i write()S w granicach PIPE_BUF, jak określono w limits.h. Gwarancje POSIX, które PIPE_BUFbędą co najmniej ...
{_POSIX_PIPE_BUF}
- Maksymalna liczba bajtów, która jest gwarantowana jako niepodzielna podczas zapisywania na potoku.
- Wartość: 512
... (który również jest domyślnym ddrozmiarem bloku we / wy) , ale rzeczywista wartość wynosi zwykle co najmniej 4k. W aktualnym systemie Linux jest to domyślnie 64k.
Więc kiedy konfigurujesz swoje ddprocesy, powinieneś to zrobić na podstawie współczynnika blokowego opartego na trzech wartościach:
- bs = (obs =
PIPE_BUFlub mniej)
- n = całkowita pożądana liczba odczytanych bajtów
- count = n / bs
Lubić:
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
Musisz zsynchronizować i / ow /, ddaby obsłużyć niewidoczne dane wejściowe. Innymi słowy, wyraź bufory potoku i przestań być problemem. Po to ddjest. Nieznana ilość tutaj jest yeswielkości bufora - ale jeśli zablokujesz ją na znanej ilości z inną, ddto małe, świadome zwielokrotnienie może dd bezpiecznie wykorzystać do kopiowania danych (bez ryzyka uszkodzenia z powodu częściowego odczytu lub zapisu) nawet gdy arbitralnie ograniczasz wejście w / count=w / dowolny typ wejścia w dowolnym systemie POSIX i bez utraty jednego bajtu.
Oto fragment specyfikacji POSIX :
ibs=expr
- Określ rozmiar bloku wejściowego, w bajtach, do (domyślnie 512) .
expr
obs=expr
- Określ rozmiar bloku wyjściowego, w bajtach, do (domyślnie 512) .
expr
bs=expr
- Ustaw rozmiar bloku wejściowego i wyjściowego na
exprbajty, zastępując ibs=i obs=. Jeśli konwersja nie inna niż sync, noerrori notruncjest określona, każdy blok wejściowy zostanie skopiowany na wyjście jako pojedynczy blok bez agregacji krótkie bloki.
Znajdziesz tu także niektóre to lepiej wyjaśnione tutaj .