2016-01-31 13 views
9

Nehmen wir an, dass die Absicht darin besteht, eine Datei mit einem großen Loch zu erstellen, auf das später geschrieben wird, auf einem Embedded-Gerät mit Linux. Wir öffnen die Datei, erhalten einen Dateideskriptor und rufen lseek darauf an, um nach einer bestimmten, bekannten Position zu suchen. Wenn wir später in die gesuchte Position schreiben wollen, rufen wir write darauf an.In Nulldatei schreiben in Linux

Beim ersten Schreibvorgang wird das Loch, das durch Suchen erzeugt wird, jedoch mit Null gefüllt, und wenn das Loch groß genug ist, kann dieser Vorgang einige Zeit dauern. In meiner Anwendung ist diese Null-Initialisierung nicht notwendig, da das Loch eine genaue Länge hat und ich es später mit meinen Daten füllen werde.

Gibt es eine Möglichkeit zu vermeiden, dass der erste write Anruf nach seek Zero-füllen Sie das Loch (auch wenn es die Änderung des Dateisystemtreibers umfasst)? Oder gibt es eine Möglichkeit, in eine Datei vor dem Anfang der Datei zu schreiben (an die Vorderseite der Datei anhängen)?

Antwort

6

Dies hängt wahrscheinlich mit Ihrem Dateisystem zusammen. Auf Ext2/3/4, Reiser, Btrfs, Xfs und dergleichen, tun, was Sie beschreiben sollten nicht lange dauern, weil sie unterstützen, was "Sparse-Dateien" (Dateien, die weniger Speicherplatz in der zugrunde liegenden Speicher als die Größe der Datei, da Nullenläufe nicht physisch gespeichert werden).

Sie könnten ein Experiment mit dd versuchen, sicherzustellen, dass dies der Fall ist:

$ dd if=/dev/zero of=whatever bs=1k seek=1073741824 count=1 
1+0 records in 
1+0 records out 
1024 bytes (1.0 kB) copied, 9.1878e-05 s, 11.1 MB/s 
$ ls -al whatever 
-rw-r--r-- 1 xxxx xxxx 1099511628800 Jan 31 18:04 whatever 
$ du -h whatever 
16K whatever 

auf Ihrem Dateisystem, das wahrscheinlich nicht. Wenn ja, und was Sie brauchen, um eine Sparse-Datei zu erstellen, bestimmen Sie, ob Sie ein anderes Dateisystem verwenden können.

+0

Sie haben Recht. In meinem Fall dauert das Ausführen von 'dd if =/dev/zero von =/mnt/mmc/was auch immer bs = 1k seek = 100000' ungefähr 10 Sekunden und die resultierende Dateigröße beträgt 97,7M.Dateisystem ist vfat, und leider kann ich das nicht ändern, da ich auf einer SD-Karte arbeite, die über mehrere Systeme lesbar sein soll. –

+0

Ja, keines der FAT-Dateisysteme unterstützt irgendeine Art von dünnem Dateispeicher, den ich kenne. Es gibt wahrscheinlich keine Möglichkeit, genau das zu erhalten, wonach Sie fragen, aber vielleicht gibt es eine gute Lösung für das eigentliche Problem, das Sie zu lösen versuchen. –

+1

@NebojsaMrmak: Werfen Sie einen Blick auf diese [andere Antwort] (http://stackoverflow.com/a/4396912/865874), HTH. – rodrigo

-1

Haben Sie versucht, die Flagge MAP_UNINITIALIZED zu verwenden?

+1

Gemäß der verknüpften Manpage ist dieses Flag nur für anonymen Speicher verfügbar, dh für Speicher, der nicht aus einer Datei stammt. – rodrigo

1

Beim ersten Schreibvorgang wird das durch Suche erzeugte Loch jedoch mit Null gefüllt und wenn das Loch groß genug ist, kann dieser Vorgang einige Zeit dauern.

Nein, kann es nicht. Es werden nur die von Ihnen angegebenen Daten in write() geschrieben. Die Nullen im ungeschriebenen Teil sind physisch nicht da: Sie sind ein Artefakt des Dateisystems.

+0

Während Ihr Kommentar wahr ist, tut es das nicht sagen, ob es einen Weg gibt, dieses Verhalten zu umgehen? Nach was ich suche, ist ein Workaround um diese Tatsache. –

+0

Wenn meine * Antwort * wahr ist, gibt es kein Verhalten zu umgehen. Die Nullbyte-Schreibvorgänge, nach denen Sie fragen, sind imaginär. Oder meine Antwort ist falsch. Du kannst es nicht auf beide Arten haben. – EJP

+1

Ungenau: Nicht alle Dateisysteme unterstützen dünn besetzte Dateien. OP benutzt vfat, was definitiv nicht der Fall ist. –

0

Dies kann aus verschiedenen Gründen keine praktikable Lösung für Ihren Anwendungsfall sein, aber ich kann mir vorstellen, die große Datei in seriell nummerierte Stücke aufzuteilen. Ein fehlender oder Zero-Size-Chunk soll Nullen (oder einen anderen festen Wert) enthalten. Wählen Sie die Chunk-Größe für den Speicherplatz, den Sie reservieren möchten, und erhalten Sie einen guten Kompromiss zwischen Dateigröße und Anzahl der Chunks.

Oder machen Sie es ein bisschen komplizierter und verwenden Sie variable Chunk-Größen, wobei die "virtuelle" Größe des einzelnen Chunk irgendwo anders gespeichert wird. Bei einem ausreichend komplexen Nummerierungssystem können Sie sogar neue Chunks einfügen, ohne die nachfolgenden Chunk-Dateien umzubenennen ...

Natürlich benötigen Sie eine zusätzliche Zugriffsebene für das De-Chunking, entweder in Ihrem Anwendungscode, wenn das ausreicht oder schlimmstenfalls als Kernel-Treiber in die Dateiverwaltung einhakt.