W systemie Ubuntu uruchamiam następujące polecenie:
dd if=/dev/random of=rand bs=1K count=2
Jednak za każdym razem, gdy go uruchamiam, kończę na pliku o innym rozmiarze. Dlaczego to? Jak mogę wygenerować plik o danym rozmiarze wypełniony losowymi danymi?
/dev/random
zablokuje się, jeśli nie będzie wystarczającej ilości entropii do wygenerowania żądanej liczby cyfr. po prostu potrzeba czasu, aby zebrać tyle wysokiej jakości losowej „losowości” psuedo ... Albo użyj/dev/urandom
mniej losowej „losowej” wartości, albo sprawdź pulę entropii (w pętli i poczekaj w razie potrzeby) ...iflag=fullblock
Odpowiedzi:
Obserwujesz połączenie osobliwego zachowania
dd
z osobliwym zachowaniem Linuksa/dev/random
. Nawiasem mówiąc, oba są rzadko odpowiednim narzędziem do pracy.Linux
/dev/random
zwraca dane oszczędnie. Opiera się na założeniu, że entropia w generatorze liczb pseudolosowych gaśnie bardzo szybko. Ponieważ gromadzenie nowej entropii jest powolne,/dev/random
zwykle rezygnuje tylko z kilku bajtów naraz.dd
to stary, zepsuty program początkowo przeznaczony do działania na urządzeniach taśmowych. Kiedy powiesz mu, żeby przeczytał jeden blok 1kB, spróbuje odczytać jeden blok. Jeśli odczyt zwraca mniej niż 1024 bajty, trudne, to wszystko, co dostajesz. Takdd if=/dev/random bs=1K count=2
czyni dwaread(2)
połączenia. Ponieważ odczytuje/dev/random
, dwaread
wywołania zwykle zwracają tylko kilka bajtów, w różnej liczbie w zależności od dostępnej entropii. Zobacz także Kiedy dd nadaje się do kopiowania danych? (lub, gdy są czytane () i write () częściowe)O ile nie projektujesz instalatora lub klonera systemu operacyjnego, nigdy nie powinieneś używać go
/dev/random
pod Linuksem, zawsze/dev/urandom
.urandom
Strona man jest nieco mylące;/dev/urandom
w rzeczywistości nadaje się do kryptografii, nawet do generowania kluczy długowiecznych. Jedynym ograniczeniem/dev/urandom
jest to, że musi być ono zaopatrzone w wystarczającą entropię; Dystrybucje Linuksa zwykle zapisują entropię między ponownymi uruchomieniami, więc jedyną chwilą, gdy nie masz wystarczającej ilości entropii, jest nowa instalacja. Entropia nie zużywa się w praktyce. Aby uzyskać więcej informacji, przeczytaj Czy rand z / dev / urandom jest bezpieczny dla klucza logowania? oraz Feeding / dev / random entropy pool? .Większość zastosowań
dd
lepiej wyrażają narzędzia takie jakhead
lubtail
. Jeśli chcesz 2kB losowych bajtów, uruchomDzięki starszym jądrom Linuksa możesz uciec
ponieważ
/dev/urandom
szczęśliwie zwrócił tyle bajtów, ile zażądano. Ale nie jest to już prawdą, ponieważ jądro 3.16 jest teraz ograniczone do 32 MB .Na ogół, gdy trzeba użyć
dd
, aby wyodrębnić określoną liczbę bajtów, a jego wejście nie nadchodzi od zwykłego pliku lub urządzenia blokowego, trzeba czytać bajt po bajcie:dd bs=1 count=2048
.źródło
/dev/urandom
zwraca 32m naread()
.dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Z
man 4 random
pudełka RHEL 5:Na tym komputerze dostaję pliki o rozmiarze 213 bajtów. Powrót do losowego mężczyzny 4:
Otrzymuję 2048 bajtów przy każdym wywołaniu
dd if=/dev/urandom of=rand bs=1K count=2
Stwierdzam, że różnica wynika z tego, ile entropii twoja maszyna generuje między wywołaniami
dd if=/dev/random ...
źródło
dd if=/dev/random bs=1K count=2
kończy się, gdy pula entropii jest najwyraźniej wyczerpana. Z dokumentów powinien się blokować, dopóki nie będzie więcej entropii, więcdd
zapisuje plik powoli, zamiast po prostu zrzucić bieżącą pulę i wyjść.read(fd, mybuf, 1024)
blokujący FD, wraca, gdy tylko urządzenie bazowe zwróci niektóre dane. Jeśli jest 1024 bajtów do odczytania, zwraca to. Jeśli jest tylko 201 bajtów, zwróci 201. Jeśli dostępnych jest 0 bajtów, zostanie zablokowany, aż przynajmniej jeden bajt stanie się dostępny, a następnie zwróci go / je.Dlaczego
dd
upuszcza dane? ... Gilles postawił to interesujące pytaniedd
:Kiedy dd nadaje się do kopiowania danych? (lub, gdy są czytane () i write () częściowe)
Oto fragment tego pytania:
* ... nietrudno jest winić dd; na przykład wypróbuj ten kod: **
yes | dd of=out bs=1024k count=10
i sprawdź rozmiar pliku wyjściowego (prawdopodobnie będzie to mniej niż 10 MB).
Oprócz mojego komentarza (na końcu twojego pytania), coś takiego jest warte obejrzenia ... Łapie twoje bajty w pliku
$trnd
. Pół arbitralnie wybrałem bs = 8Poruszaj myszką i patrz, jak przyspiesza.
Gdy mój komputer był bezczynny (AFK i brak aktywności sieciowej), a po wyczerpaniu puli entropii zebranie tylko 1192 bajtów zajęło 2 godziny i 12 minut , w którym to momencie anulowałem.
Następnie, gdy ja ciągle poruszałem myszą, zajęło to stosunkowo dużo mniej 1 minutę i 15 sekund na zebranie tej samej liczby bajtów.
Pokazuje to dość wyraźnie, że gromadzenie entropii nie jest oparte na szybkości procesora, ale raczej na losowych zdarzeniach i że mój system Ubuntu używa myszy jako jednego z istotnych czynników losowych.
źródło
dd
jest przeznaczony do blokowania - jest to zwykle najlepsze narzędzie do Twojej dyspozycji do odczytu ze zmiennych danych wejściowych, jeśli potrzebujesz tego natychmiast, ponieważdd
nie buforuje bieżących odczytów w przyszłościwrite()
(chyba że bardzo wyraźnie skonfigurujesz to w ten sposób z większym obsłem niż ibs) , ale zamiastwrite()
wszystko to brzmi tak szybko, jakread()
to wszystko (i ewentualnie przetwarza je) .Oto kilka ważnych definicji :
ibs=
expr
expr
obs=
expr
expr
bs=
expr
expr
bajty, zastępującibs=
iobs=
. Jeśli konwersja nie inna niżsync
,noerror
inotrunc
jest określona, każdy blok wejściowy zostanie skopiowany na wyjście jako pojedynczy blok bez agregacji krótkie bloki.Widzisz więc, kiedy
ibs
iobs
są zdefiniowane razem, ponieważbs
wtedyibs
ma pierwszeństwo - ale w przeciwnym razie, jeśli jesteś konkretny, to alboobs
albocbs
.Oto przykład, w którym
ibs
jest najważniejszy. Możesz zrobić coś takiego, jeśli chcesz śledzić, jak szybko/dev/random
basen się zapełni ...Dopóki
if=
„s celem jest czytelny w ogóle, że będzie zawsze prowadzić w tej samej wielkości pliku wynikowego, ponieważdd
będziesync
hronize bloki odczytu w na null. Innymi słowy, jeślidd
read()
s dla wejściowego bloku$((size=10))
$((count=5))
czasów, aread()
plik zwraca 2 bajty, to 8 bajtów, następnie 12 bajtów, następnie 2 bajty, a następnie 4 bajty,dd
zapisze w swoim pliku wyjściowym coś w rodzaju... ponieważ
dd
domyślnie nie opóźnia. Jeśli więc chcesz śledzić in-stream i ograniczyć zapisy innego procesu,dd
to jest to narzędzie dla Ciebie.Jeśli po prostu zapisujesz pewną ilość danych do zwykłego pliku, w przeciwieństwie do innych oświadczeń tutaj zawartych, możesz również użyć
dd
do tego - i dość łatwo - ale potrzebujesz więcej niż jednego i niezawodnego czynnika blokującego .Na przykład, jeśli zrobiłeś:
... pierwszy
dd
buforowałby tyleibs="$size"
bloków wejściowych, ile było niezbędnych do wypełnienia co najmniej jednegoobs="${size}x$block_factor"
bloku wyjściowego dla każdegowrite()
potoku między nim a drugimdd
. Oznacza to, że drugidd
może niezawodnie ograniczyć moc wyjściową,count="$lmt"
ponieważ wszystkiewrite()
pierwsze marki będą pasować do swojego rozmiaru bloku we / wy - niezależnie od tego, ileread()
sdd
musi zrobić pierwszy .W ten sposób możesz
dd
niezawodnie czytać potoki lub inne typy plików specjalnych - z odrobiną matematyki.źródło