2012-08-05 1 views
15

Diese Frage denke ich ist technisch genug für S/O, und wahrscheinlich auch zu programmieren-orientierte für Android. Ich bin fasziniert, wie Dateien in Android (oder Java oder Linux, wie angemessen) gehandhabt werden, da ich etwas mit meinem neuen Smartphone gemacht habe und ich würde gerne wissen, wie es passiert ist.Warum kann ich eine Datei unter Linux erfolgreich verschieben, während sie geschrieben wird?

Ich habe eine Datei von meinem Laptop auf mein Android-Handy über Bluetooth übertragen. Ich habe die neue Datei im Dateiexplorer gesehen, angenommen, dass sie vollständig übertragen wurde, und sie so von /sdcard/bluetooth zu /sdcard/torrents verschoben. Nachdem ich das getan hatte, bemerkte ich, dass es tatsächlich noch übertragen wurde. Zu meiner Überraschung wurde es erfolgreich abgeschlossen, bestätigt mit einem Benachrichtigungssymbol im Telefon und durch eine manuelle MD5-Überprüfung auf beiden Seiten. In den meisten Systemen hätte die Dateiverschiebung einen Absturz verursacht.

Was ist der Grund für diese erfolgreiche Übertragung? Mir ist bekannt, dass der Dateipfad im Allgemeinen vom Dateispeicherort im Dateisystem (in diesem Fall eine SD-Karte) getrennt ist. Ich stelle mir vor, dass die Bluetooth-App ein Handle für die Datei geöffnet hat, und als ich die Datei verschoben habe, wurde eine Tabelle mit "geöffneten Dateien" mit einem neuen Pfad aktualisiert. Gilt diese Funktion generell für jedes Linux-System? Könnte ich eine mv für eine Datei schreiben und erwarten, dass die Kopie - an ihrem neuen Speicherort - korrekt ist?

+0

Warum sollte das Verschieben von Dateien zwischen zwei verursachen einen Absturz verschiedene Dateisysteme zu beginnen? Die Dateien selbst sind Kludges von Binärdaten; Das Dateisystem stellt nur dar, wie diese Datenmenge gespeichert, dargestellt und entfernt wird. – Makoto

+1

Das Verschieben einer Datei in sich würde nicht zu einem Absturz führen, aber 'mv' für eine Datei _während es noch in to_ geschrieben wird, würde wahrscheinlich (da im Allgemeinen ein System, das in eine Datei schreibt, davon ausgehen können sollte Die Datei bleibt vom Schreib-Öffnen bis zum Schreiben-Schließen am selben Ort. Ich versuche zu verstehen, ob der letzte Fall für alle Linux (oder Java oder Android) Systeme gilt. Extra Scout/Brownie Punkte für jeden, der erklären kann, warum das gelingt! – halfer

Antwort

31

Wenn Sie eine Datei im gleichen Filesystem bewegen, die Datei selbst (die inode) wird nicht bewegt. Das einzige, was sich ändert, sind die Verzeichniseinträge in diesem Dateisystem. (Der Systemaufruf von mv in diesem Fall in Anspruch genommen ist rename(2) - überprüfen Sie die Seite für zusätzliche Informationen und Einschränkungen.)

Wenn ein Prozess eine Datei öffnet, wird der Dateiname an das OS übergeben, um anzuzeigen, welche Datei gemeint ist, aber die Datei-Deskriptor, den Sie zurückbekommen, ist überhaupt nicht mit diesem Namen verbunden (Sie können keinen Dateinamen von ihm zurückbekommen) – es ist mit dem Inode verbunden.
Da der Inode beim Umbenennen einer Datei (innerhalb desselben Dateisystems) unverändert bleibt, können Prozesse, die ihn geöffnet haben, problemlos weiterlesen und darauf schreiben – hat sich für sie nichts geändert, ihr Dateideskriptor ist immer noch gültig und zeigt nach rechts Daten.

Das Gleiche, wenn Sie eine Datei löschen. Prozesse können weiterhin lesen und schreiben, selbst wenn die Datei nicht mehr über einen Verzeichniseintrag erreichbar ist. (Dies kann zu verwirrenden Situationen führen, in denen df meldet, dass Ihr Datenträger voll ist, aber du sagt, dass Sie viel weniger Speicherplatz verwenden, den df meldet. Die Blöcke, die gelöschten Dateien zugewiesen sind, die noch geöffnet sind, werden nicht freigegeben, bis diese Prozesse ihre schließen Dateideskriptor.)

Wenn die mv die Datei über Dateisysteme verschiebt, ist das Verhalten anders, da Inodes für jedes Dateisystem spezifisch sind. In diesem Fall kopiert mv die Daten tatsächlich und erstellt einen neuen Inode (und Verzeichniseintrag) auf dem Zieldateisystem. Wenn die Kopie beendet ist, wird die alte Datei entkoppelt und entfernt, wenn keine offenen Dateihandles darauf sind, wie oben.
In Ihrem Fall, wenn Sie eine Dateisystemgrenze überschritten haben, haben Sie eine Teildatei im Ziel. Und Ihr Upload-Prozess schreibt glücklich in eine gelöschte Datei, auf die Sie nicht einfach zugreifen können, und füllt möglicherweise das Dateisystem auf, bis der Upload abgeschlossen ist und der Inode dann fallen gelassen wird.

Einige Beiträge über Unix & Linux, die Sie interessant finden könnte:

+0

Große Antwort, danke Mat. Ja, ich habe die Datei in das Dateisystem verschoben. Ich habe einige Jahre auf Unix-ähnlichen Systemen entwickelt, aber diese Fähigkeit habe ich vorher nicht kennengelernt. Ich hätte erwartet, dass es den Schreibprozess gestört hätte. Ziemlich clevere Sachen! – halfer