BEZEICHNUNG
close - Dateideskriptor schließen
ÜBERSICHT
#include <unistd.h>
int close(int fd);
BESCHREIBUNG
close() schließt einen Dateideskriptor, so dass dieser nicht mehr zu einer Datei gehört und wieder verwendet werden kann. Alle zum Prozess gehörenden Datensatz-Sperren (siehe fcntl(2)) der mit dem Deskriptor verbundenen Datei werden aufgehoben. Die Aufhebung der Sperren erfolgt unabhängig von dem Deskriptor, mit dem die Sperre eingerichtet wurde.
Wenn fd der letzte Deskriptor der zugehörigen offenen Datei ist (siehe open(2)), werden die zugehörigen Ressourcen freigegeben. War der Datei-Deskriptor der letzte Verweis auf eine Datei, die mittels unlink(2) entfernt wurde, wird die Datei gelöscht.
RÜCKGABEWERT
Nach erfolgreicher Ausführung gibt close() 0 zurück. Bei Fehlern wird -1 zurückgegeben und errno entsprechend gesetzt.
FEHLER
EBADF |
fd ist kein gültiger Deskriptor für eine geöffnete Datei. | ||
EINTR |
Der Aufruf von close() wurde von einem Signal unterbrochen (siehe signal(7)). | ||
EIO |
Es ist ein E/A-Fehler (engl. I/O) aufgetreten. |
ENOSPC, EDQUOT
Auf NFS werden diese Fehler normalerweise nicht beim ersten Schreibversuch, der den verfügbaren Speicherplatz überschreitet, berichtet, sondern stattdessen an nachfolgende write(2), fsync(2) oder close(2).
Siehe ANMERKUNGEN für eine Diskussion, warum close() nach einem Fehler nicht erneut versucht werden sollte.
KONFORM ZU
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
ANMERKUNGEN
Ein erfolgreiches »close« garantiert nicht, dass die Daten erfolgreich auf der Festplatte gespeichert wurden, weil der Kernel den Pufferzwischenspeicher verwendet, um verzögert zu schreiben. Typischerweise leeren Dateisysteme ihre Puffer beim Schließen einer Datei nicht. Wenn Sie sicher sein müssen, dass die Daten physisch auf der darunterliegenen Platte gespeichert sind, verwenden Sie fsync(2). (Hierbei kommt es auf die Hardware Ihrer Festplatte an.)
Der Dateideskriptor close-on-exec kann dazu verwandt werden, sicherzustellen, dass ein Dateideskriptor automatisch bei einem erfolgreichen execve(2) geschlossen wird; siehe fcntl(2) für Details.
Multithreaded-Prozesse
und close()
Wahrscheinlich ist es unklug, Dateideskriptoren zu
schließen, die möglicherweise noch durch
Systemaufrufe in anderen Threads desselben Prozesses belegt
sein können. Da Dateideskriptoren wiederverwendet
werden können, kann dies zu undurchsichtigen
»Race Conditions« mit unbeabsichtigten
Nebenwirkungen führen.
Betrachten Sie des Weiteren folgendes Szenario, bei dem zwei Threads Aktionen auf den gleichen Dateideskriptor ausführen:
1. |
Ein Thread blockiert auf einem E/A-Systemaufruf auf dem Dateideskriptor. Beispielsweise versucht er in eine Pipe zu schreiben (write(2)), die bereits voll ist, oder versucht aus einem Datenstrom-Socket zu lesen (read(2)), der derzeit über keine Daten verfügt. | ||
2. |
Ein anderer Thread schließt den Dateideskriptor. |
Das Verhalten in dieser Situation unterscheidet sich zwischen Systemen. Auf einigen Systemen kehrt der blockierte Systemaufruf sofort mit einem Fehler zurück, wenn der Dateideskriptor geschlossen wird.
Unter Linux (und möglicherweise einigen anderen Systemen) ist das Verhalten anders. Der blockierende E/A-Systemaufruf hält eine Referenz auf die zugrundeliegende offene Dateideskription und diese Referenz hält die Deskription offen, bis der E/A-Systemaufruf abschließt. (Siehe open(2) für eine Diskussion von offenen Dateideskriptionen). Daher kann sich der blockierende Systemaufruf in dem ersten Thread nach einem close() in dem zweiten Thread erfolgreich beenden.
Umngang mit
von close() zurückgelieferten Fehlern
Ein sorgfältiger Programmierer prüft den
Rückgabewert von close(), da es durchaus
möglich ist, dass Fehler bei einer früheren
write(2)-Operation erst bei dem abschließenden
close()-Zugriff, bei dem die offenen
Dateideskriptoren freigegeben werden, gemeldet werden. Wird
der Rückgabewert beim Schließen einer Datei nicht
geprüft, kann dies zu unbemerktem Datenverlust
führen. Dies kann vor allem mit NFS und
Plattenkontingenten beobachtet werden.
Beachten Sie allerdings, dass ein zurückgelieferter Fehler nur für diagnostische Zwecke (d.h. einer Warnung an die Anwendung, dass E/A noch in Verarbeitung ist, oder dass es fehlgeschlagene E/A gegeben haben könnte) oder für abhelfende Zwecke (z.B. dem erneuten Schreiben der Datei oder dem Erstellen einer Sicherungskopie) verwandt werden sollte.
Es ist falsch, nach einer Rückgabe eines Fehlers close() erneut zu versuchen, da es dazu führen könnte, dass ein wiederverwandter Dateideskriptor von einem anderen Thread geschlossen werden könnte. Dies kann auftreten, da der Linux-Kernel Dateideskriptoren immer früh in der Close-Aktion für die Wiederbenutzung freigibt und die Schritte, die einen Fehler liefern können, wie das Rausschreiben von Daten zu dem Dateisystem oder Gerät, erst später in der Close-Aktion vorkommen.
Viele andere Implementierunngen schließen den Dateideskriptor ähnlich (außer im Falle von EBADF, der bedeutet, dass der Dateideskriptor ungültig war), selbst falls sie im folgenden einen Fehler bei der Rückkehr von close() berichten. POSIX.1 sagt derzeit zu diesem Punkt nichts aus, aber es gibt Überlegungen, dieses Verhalten in der nächsten großen Veröffentlichung dieses Standards zu verpflichten.
Ein sorgfältiger Programmierer, der über E/A-Fehler Bescheid wissen möchte, kann close() einen Aufruf von fsync(2) vorschalten.
Der Fehler EINTR ist etwas speziell. Bezüglich des Fehlers EINTR sagt POSIX.1-2008:
Falls close() von einem Signal unterbrochen wird, das gefangen werden soll, muss es -1 zurückliefern, wobei errno auf EINTR gesetzt werden soll und der Zustand von fildes nicht festgelegt ist.
Dies erlaubt das Verhalten, das auf Linux und vielen anderen Implementierungen auftritt, bei dem, wie auch bei anderen von close() berichteten Fehlern, garantiert wird, dass der Dateideskriptor geschlossen ist. Es erlaubt allerdings auch eine andere Möglichkeit: dass die Implementierung einen Fehler EINTR zurückliefert und den Dateideskriptor offen hält. (Laut seiner Beschreibung ist dies für close() unter HP-UX der Fall.) Der Aufrufende muss dann erneut close() verwenden, um den Dateideskriptor zu schließen und Lecks bei Dateideskriptoren zu vermeiden. Diese Divergenz in Implementierungsverhalten stellt eine schwierige Hürde für portable Anwendungen dar, da unter vielen Implementierungen close() nicht nach einem Fehler EINTR erneut aufgerufen werden darf, und bei mindestens einer close() erneut aufgerufen werden muss. Es gibt Überlegungen, dieses Puzzle für die nächste Hauptveröffentlichung des Standards POSIX.1 zu lösen.
SIEHE AUCH
fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)
KOLOPHON
Diese Seite ist Teil der Veröffentlichung 5.07 des Projekts Linux-man-pages. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Ralf Demmer <rdemmer [AT] rdemmer.de>, Martin Eberhard Schauer <Martin.E.Schauer [AT] gmx.de>, Mario Blättermann <mario.blaettermann [AT] gmail.com> und Helge Kreutzmann <debian [AT] helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an <debian-l10n-german [AT] lists.org>.