it-swarm.com.de

dd erstellt eine 32 MB große Zufallsdatei anstelle von 1 GB

Ich wollte eine 1-GB-Zufallsdatei erstellen und habe den folgenden Befehl verwendet.

dd if=/dev/urandom of=output bs=1G count=1

Stattdessen erhalte ich jedes Mal, wenn ich diesen Befehl starte, eine 32-MB-Datei:

<11:58:40>$ dd if=/dev/urandom of=output bs=1G count=1
0+1 records in
0+1 records out
33554431 bytes (34 MB, 32 MiB) copied, 0,288321 s, 116 MB/s

Was ist falsch?

BEARBEITEN:

Dank großartiger Antworten in diesem Thema kam ich mit einer Lösung, die 32 Chunks mit einer Größe von 32 MB liest und 1 GB ergibt:

dd if=/dev/urandom of=output bs=32M count=32

Es wurde eine andere Lösung angegeben, die 1 GB direkt in den Speicher liest und dann auf die Festplatte schreibt. Diese Lösung benötigt viel Speicher und wird daher nicht bevorzugt:

dd if=/dev/urandom of=output bs=1G count=1 iflag=fullblock
49
Trismegistos

bs, die Puffergröße, bezeichnet die Größe eines einzelnen read () -Aufrufs von dd.

(Beispielsweise führen sowohl bs=1M count=1 als auch bs=1k count=1k zu einer 1-MB-Datei, die erste Version erledigt dies jedoch in einem einzigen Schritt, während die zweite Version dies in 1024 kleinen Blöcken erledigt.)

Normale Dateien können mit nahezu jeder Puffergröße gelesen werden (solange dieser Puffer in den Arbeitsspeicher passt), aber Geräte und "virtuelle" Dateien arbeiten häufig sehr nahe an den einzelnen Aufrufen und unterliegen einer willkürlichen Einschränkung der Datenmenge, die sie pro Aufruf erzeugen read () Aufruf.

Für /dev/urandom ist dieses Limit in urandom_read () in drivers/char/random.c definiert:

#define ENTROPY_SHIFT 3

static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
    nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
    ...
}

Dies bedeutet, dass bei jedem Aufruf der Funktion die angeforderte Größe auf 33554431 Byte begrenzt wird.

Im Gegensatz zu den meisten anderen Tools wird dd standardmäßig nicht wiederholt, nachdem weniger Daten als angefordert empfangen wurden - Sie erhalten die 32 MiB und das wars. (Damit es automatisch wiederholt wird, wie in Kamils ​​Antwort, müssen Sie iflag=fullblock angeben.)


Beachten Sie auch, dass "die Größe eines einzelnen read ()" bedeutet, dass der gesamte Puffer auf einmal in den Speicher passen muss, sodass massive Blockgrößen auch einer massiven Speichernutzung durch dd entsprechen.

Und es ist alles sinnlos, weil Sie normalerweise keine Leistung erzielen, wenn Sie über ~ 16–32 MiB-Blöcke hinausgehen - Syscalls sind hier nicht der langsame Teil, sondern der Zufallszahlengenerator.

Verwenden Sie zur Vereinfachung einfach head -c 1G /dev/urandom > output.

92
grawity

ddkann weniger als ibslesen (Anmerkung: bsgibt sowohl ibsals auch obsan), sofern nicht iflag=fullblock angegeben ist. 0+1 records in zeigt an, dass 0 vollständige Blöcke und 1 teilweise Blöcke gelesen wurden. Jeder vollständige oder teilweise Block erhöht jedoch den Zähler.

Ich kenne den genauen Mechanismus nicht, mit dem ddeinen Block liest, der in diesem speziellen Fall kleiner als 1G ist. Ich vermute, ein Block wird vor dem Schreiben in den Speicher gelesen, sodass die Speicherverwaltung möglicherweise stört (dies ist jedoch nur eine Vermutung). Bearbeiten: diese gleichzeitige Antwort erklärt den Mechanismus, der bewirkt, dass ddeinen Block liest, der in diesem speziellen Fall kleiner als 1G ist.

Auf jeden Fall empfehle ich nicht so große bsname__. Ich würde bs=1M count=1024 verwenden. Das Wichtigste ist: Ohne iflag=fullblock kann jeder Leseversuch weniger als ibslesen (es sei denn, ibs=1 ist meiner Meinung nach recht ineffizient).

Wenn Sie also eine genaue Datenmenge lesen müssen, verwenden Sie iflag=fullblock. Hinweis iflagwird von POSIX nicht benötigt, Ihr ddunterstützt dies möglicherweise nicht. Laut diese Antwortibs=1 ist wahrscheinlich die einzige POSIX-Methode, um eine genaue Anzahl von Bytes zu lesen. Wenn Sie ibsändern, müssen Sie natürlich den countnamen__ neu berechnen. In Ihrem Fall wird das Problem wahrscheinlich behoben, wenn Sie ibsauf 32M oder weniger senken, auch ohne iflag=fullblock.

In meinem Kubuntu würde ich deinen Befehl so korrigieren:

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
21