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


50

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

3
Meiner Meinung nach gibt es für überhaupt nicht viele gültige Anwendungsfälle dd. Ich würde verwenden head, catoder rsyncan seiner Stelle fast immer. Und Ihre Frage, ob einer der Gründe, warum die Alternativen in der Regel sicherer sind.
Bakuriu

@Bakuriu - auch wenn Sie nur eine Datei voller Nullen erstellen möchten (oder sich nicht darum kümmern, was sich darin befindet), verwenden Sie "Truncate". Es geht viel schneller.
Konrad Gajewski

@ KonradGajewski FYI abgeschnitten versucht, eine spärliche Datei zu machen (wenn das zählt)
Xen2050

5
@Bakuriu headkann diese Aufgabe nicht ohne die -cOption ausführen , die nicht in POSIX enthalten ist . Ich kenne keine Version, catdie das lösen kann. rsyncist ein völlig anderes Dienstprogramm. Das ist weder hier noch dort; Beim Durchblättern der Manpage sehe ich auch keine Möglichkeit, dieses Problem zu lösen.
Kaz

Technisch /dev/urandomist es auch nicht in POSIX ...
grawity

Antworten:


92

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

(Beide bs=1M count=1und bs=1k count=1kführen beispielsweise zu einer 1-MiB-Datei, die erste Version erledigt dies jedoch in einem Schritt, die zweite in 1024 kleinen Blöcken.)

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/urandomist 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 keine Neuversuche durchführen, nachdem weniger Daten als angefordert empfangen wurden - Sie erhalten die 32 MiB und das wars. (Damit es automatisch wiederholt wird, müssen Sie wie in Kamils ​​Antwort angeben iflag=fullblock.)


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 Zufallsgenerator.

Also der Einfachheit halber einfach benutzen head -c 1G /dev/urandom > output.


7
„... Sie werden in der Regel keine Leistung gewinnen , wenn sie über ~ 16-32 MiB Blöcke gehen“ - Nach meiner Erfahrung, Sie sind in der Regel nicht viel zu gewinnen oder sogar verliert Leistung über 64 bis 128 Kilo - Byte. Zu diesem Zeitpunkt sind Sie in den sinkenden Kosten für Systemaufrufe gut aufgehoben, und Cache-Konflikte spielen allmählich eine Rolle.
März

3
@marcelm Ich habe bei der Entwicklung von Hochleistungssystemen geholfen, bei denen sich die E / A-Leistung verbessern würde, wenn die Blockgröße auf 1-2 MB-Blöcke und in einigen Fällen auf bis zu 8 MB erhöht würde. Pro LUN. Und da Dateisysteme mit mehreren parallelen LUNs erstellt wurden, bedeutet dies, dass für die bestmögliche Leistung mehrere Threads für E / A verwendet werden, die jeweils 1 MB + Blöcke ausführen. Anhaltende IO-Raten lagen über 1 GB / s. Und das waren alles sich drehende Festplatten, sodass ich feststellen kann, dass Hochleistungs-SSD-Arrays immer schneller Daten verschlucken oder generieren, wenn die Blockgröße auf 16 oder sogar 32 MB-Blöcke ansteigt. Leicht. Vielleicht noch größer.
Andrew Henle

4
Ich werde ausdrücklich darauf hinweisen, dass dies iflag=fullblockeine GNU-Erweiterung des POSIX- ddDienstprogramms ist . Da die Frage Linux nicht spezifiziert, sollte die Verwendung von Linux-spezifischen Erweiterungen wahrscheinlich explizit erwähnt werden, damit zukünftige Leser, die versuchen, ein ähnliches Problem auf einem Nicht-Linux-System zu lösen, nicht verwirrt werden.
Andrew Henle

6
@ AndrewHenle Ah, interessant! Ich habe einen kurzen Test mit ddauf meiner Maschine durchgeführt, mit Blockgrößen von 1k bis 512M. Mit einer Intel 750 SSD wurde eine optimale Leistung (ca. 1300 MB / s) bei 2 MB-Blöcken erzielt, die in etwa Ihren Ergebnissen entspricht. Größere Blöcke haben weder geholfen noch gehindert. Die /dev/zerooptimale Leistung (fast 20 GB / s) lag bei 64 KB- und 128 KB-Blöcken. Sowohl kleinere als auch größere Blöcke verringerten die Leistung und entsprachen in etwa meinem vorherigen Kommentar. Fazit: Benchmark für Ihre aktuelle Situation. Und natürlich hat keiner von uns ein Benchmarking durchgeführt /dev/random: P
marcelm 28.12.18

3
@ Xen2050 ich habe noch ein paar schnelle tests gemacht, und es scheint ddschneller zu sein. Eine kurze Zusammenfassung zeigte, dass head8-KB-Lesevorgänge und zwei 4-KB-Schreibvorgänge verwendet werden, was interessant ist (GNU coreutils 8.26 unter Debian 9.6 / Linux 4.8). headGeschwindigkeiten liegen in der Tat irgendwo zwischen dd bs=4kund dd bs=8k. headGeschwindigkeiten sinken um ~ 40% gegenüber dd if=/dev/zero bs=64kund um ~ 25% gegenüber dd if=/dev/nvme0n1 bs=2M. Die Lesevorgänge /dev/zerosind natürlich stärker CPU-begrenzt, aber für die SSD-E / A spielt auch die Warteschlange eine Rolle. Es ist ein größerer Unterschied als ich erwartet hatte.
März

21

ddkann kleiner sein als ibs(Anmerkung: bsgibt beides ibsund an obs), sofern iflag=fullblocknicht anders angegeben. 0+1 records inzeigt an, dass 0vollständige und 1teilweise Blöcke gelesen wurden. Jeder vollständige oder teilweise Block erhöht jedoch den Zähler.

Ich kenne nicht den genauen Mechanismus, der das ddLesen eines Blocks bewirkt, der kleiner ist als 1Gin diesem speziellen Fall. 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, mit dem ddein Block gelesen wird, der kleiner ist als 1Gin diesem speziellen Fall.

Jedenfalls empfehle ich nicht so groß bs. Ich würde verwenden bs=1M count=1024. Das Wichtigste ist: Ohne iflag=fullblock einen Leseversuch kann weniger als gelesen werden ibs(es sei denn ibs=1, ich denke, dies ist recht ineffizient).

Wenn Sie also eine genaue Datenmenge lesen müssen, verwenden Sie iflag=fullblock. Hinweis iflagwird von POSIX nicht benötigt, ddmöglicherweise wird dies nicht unterstützt. Nach dieser Antwort ibs=1 ist wahrscheinlich die einzige POSIX-Methode, um eine genaue Anzahl von Bytes zu lesen. Wenn Sie sich ändern, müssen ibsSie das natürlich neu berechnen count. In Ihrem Fall wird das Problem wahrscheinlich auch ohne eine Senkung ibsauf 32Moder weniger behoben iflag=fullblock.

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

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.