Provided by: manpages-de-dev_4.21.0-2_all 

BEZEICHNUNG
fcntl - Dateideskriptoren manipulieren
BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)
ÜBERSICHT
#include <fcntl.h>
int fcntl(int dd, int Bef, … /* arg */ );
BESCHREIBUNG
fcntl() führt eine der unten beschriebenen Aktionen auf dem offenen Dateideskriptor dd aus. Die Aktion
wird durch Bef festgelegt.
fcntl() kann ein optionales drittes Argument akzeptieren. Ob dieses Argument notwendig ist, ergibt sich
durch Bef. Der benötigte Argumenttyp wird nach jedem Bef-Namen in Klammern angedeutet (in den meisten
Fällen ist der benötigte Typ int und der Argumenttyp wird mit dem Namen arg identifiziert). Falls das
Argument nicht notwendig ist, wird void angegeben.
Bestimmte der unten aufgeführten Aktionen werden nur seit einer bestimmten Linux-Kernelversion
unterstützt. Die bevorzugte Methode, um herauszufinden, ob der Gastkernel eine bestimmte Aktion
unterstützt, ist der Aufruf von fcntl() mit dem gewünschten Wert von Bef und dem anschließenden Test, ob
der Aufruf mit EINVAL fehlschlug, wodurch angezeigt wird, dass der Kernel diesen Wert nicht unterstützt.
Duplizieren eines Dateideskriptors
F_DUPFD (int)
verdoppelt den Dateideskriptor dd unter Verwendung des Dateideskriptors mit der kleinsten Nummer,
die identisch zu oder größer als arg ist. Dies unterscheidet sich von dup2(2), das exakt den
angegebenen Dateideskriptor verwendet.
Bei Erfolg wird der neue Dateideskriptor zurückgegeben.
Lesen Sie dup(2) für weitere Details.
F_DUPFD_CLOEXEC (int; seit Linux 2.6.24)
Wie für F_DUPFD, setzt aber zusätzlich den Schalter »close-on-exec« für den duplizierten
Dateideskriptor. Die Angabe dieses Schalters ermöglicht es einem Programm, eine zusätzliche
fcntl()-F_SETFD-Aktion zu vermeiden, um den Schalter FD_CLOEXEC zu setzen. Für eine Erläuterung,
warum dieser Schalter nützlich ist, lesen Sie die Beschreibung von O_CLOEXEC in open(2).
Datei-Deskriptor-Schalter
Die folgenden Befehle verändern die einem Dateideskriptor zugeordneten Schalter. Derzeit ist nur ein
solcher Schalter definiert: FD_CLOEXEC, der »close-on-exec«-Schalter. Falls das FD_CLOEXEC-Bit gesetzt
ist, wird der Dateideskriptor automatisch bei einem erfolgreichen execve(2) geschlossen. (Falls der
execve(2) fehlschlägt, bleibt der Dateideskriptor offen.) Falls das Bit FD_CLOEXEC nicht gesetzt ist,
wird der Dateideskriptor über ein execve(2) hinweg offen bleiben.
F_GETFD (void)
Liefert (als Ergebnis der Funktion) die Dateideskriptorschalter; arg wird ignoriert.
F_SETFD (int)
Setzt den Dateideskriptorschalter auf den durch arg angegebenen Wert.
In Programmen mit mehreren Threads ist die Verwendung von fcntl() F_SETFD, um den Schalter
»close-on-exec« zum gleichen Zeitpunkt zu setzen, zu dem ein anderer Thread ein fork(2) mit einem
execve(2) ausführt, anfällig für einen Ressourcenwettlauf, der unbeabsichtigterweise den Dateideskriptor
an das Programm, das im Kindprozess läuft, durchsickern lässt. Siehe die Diskussion des Schalters
O_CLOEXEC in open(2) für Details und wie dem Problem abgeholfen werden kann.
Dateistatusschalter
Jede offene Dateideskription hat bestimmte zugeordnete Statusschalter, die durch open(2) initialisiert
und möglicherweise durch fcntl() verändert werden. Duplizierte Dateideskriptoren (mit dup(2),
fcntl(F_DUPFD), fork(2) usw. erstellte) beziehen sich auf die gleiche offene Dateideskription und teilen
sich daher die gleichen Dateistatusschalter.
Die Dateistatusschalter und deren Bedeutung sind in open(2) beschrieben.
F_GETFL (void)
Liefert (als Ergebnis der Funktion) den Dateizugriffsmodus und die Dateistatusschalter; arg wird
ignoriert.
F_SETFL (int)
Setzt die Dateistatusschalter auf den durch arg angegebenen Wert. Dateizugriffsmodus (O_RDONLY,
O_WRONLY, O_RDWR) und Dateierzeugungsschalter (d.h. O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) werden in
arg ignoriert. Unter Linux kann dieser Befehl nur die Schalter O_APPEND, O_ASYNC, O_DIRECT,
O_NOATIME und O_NONBLOCK ändern. Es ist nicht möglich, die Schalter O_DSYNC und O_SYNC zu ändern,
siehe FEHLER weiter unten.
Empfohlene Datensatzsperren
Linux implementiert traditionelle (»Prozess-orientierte«) UNIX-Datensatz-Sperren, wie durch POSIX
standardisiert. Für eine Linux-spezifische Alternative mit besserer Semantik lesen Sie die Diskussion
über offene Dateideskriptions-Sperren unten.
F_SETLK, F_SETLKW und F_GETLK werden dazu verwandt, Datensatzsperren (auch bekannt als Byte-Bereichs-,
Dateisegment- oder Dateiregionsperren) zu erlangen, abzugeben oder auf deren Existenz zu prüfen. Das
dritte Argument, lock, ist ein Zeiger auf eine Struktur, die mindestens die folgende Felder (in einer
nicht festgelegten Reihenfolge) enthält:
struct flock {
…
short l_type; /* Art der Sperre: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* Wie l_start interpretiert wird:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Anfangsversatz für Sperre */
off_t l_len; /* Anzahl von zu sperrenden Bytes */
pid_t l_pid; /* PID des Prozesses, der unsere Sperre blockiert
(gesetzt durch F_GETLK und F_OFD_GETLK) */
…
};
Die Felder l_whence, l_start und l_len dieser Struktur legen den Bereich der Bytes, die gesperrt werden
sollen, fest. Bytes hinter dem Ende der Datei können gesperrt sein, aber Bytes vor dem Anfang der Datei
sind es nicht.
l_start ist der Startversatz für die Sperre und wird relativ zu einem der folgenden interpretiert: Dem
Anfang der Datei (falls l_whence SEEK_SET ist), dem aktuellen Dateiversatz (falls l_whence SEEK_CUR ist)
oder dem Ende der Datei (falls l_whence SEEK_END ist). In den abschließenden zwei Fällen kann l_start
eine negative Zahl sein, vorausgesetzt, der Versatz liegt nicht vor dem Anfang der Datei.
l_len legt die Anzahl der zu sperrenden Bytes fest. Falls l_len positiv ist, wird der zu sperrende
Bereich die Bytes l_start bis einschließlich l_start+l_len-1 umfassen. Die Angabe von 0 für l_len hat
eine besondere Bedeutung: Alle Bytes beginnend bei l_whence und l_start bis zum Ende der Datei sperren,
unabhängig davon, wie groß die Datei anwächst.
POSIX.1-2001 erlaubt (verlangt es aber nicht), dass eine Implementierung einen negativen Wert für l_len
unterstützt. Falls l_len negativ ist, deckt das durch lock beschriebene Intervall die Bytes l_start+l_len
bis zu einschließlich l_start-1 ab. Dies wird durch Linux seit 2.4.21 und 2.5.49 unterstützt.
Das Feld l_type kann dazu verwandt werden, eine Lese- (F_RDLCK) oder Schreibsperre (F_WRLCK) auf eine
Datei zu setzen. Eine beliebige Anzahl an Prozessen kann eine Lesesperre auf eine Dateiregion halten
(gemeinsame Sperre), aber nur ein Prozess kann eine Schreibsperre (exklusive Sperre) halten. Eine
exklusive Sperre sperrt alle anderen Sperren aus, sowohl exklusive als auch gemeinsame. Ein einzelner
Prozess kann nur eine Art von Sperre auf eine Dateiregion halten. Falls eine neue Sperre auf eine bereits
gesperrte Region angewandt wird, wird die existierende Sperre in den Typ der neuen Sperre umgewandelt.
(Solche Umwandlungen können das Teilen, Verkleinern, Vereinigen mit bestehenden Sperren beinhalten, falls
der durch die neue Sperre festgelegte Byte-Bereiche nicht genau mit dem Bereich der bereits existierenden
Sperre zusammenfällt.)
F_SETLK (struct flock *)
Erlangt (wenn l_type F_RDLCK oder F_WRLCK ist) oder gibt eine Sperre (wenn l_type F_UNLCK ist) für
die durch die Felder l_whence, l_start und l_len von lock festgelegten Bytes ab. Falls durch einen
anderen Prozess eine im Konflikt stehende Sperre gehalten wird, liefert dieser Aufruf -1 zurück
und setzt errno auf EACCES oder EAGAIN. (Der in diesem Fall zurückgelieferte Fehler unterscheidet
sich zwischen Implementierungen, daher verlangt POSIX, dass portable Anwendungen auf beide Fehler
prüfen.)
F_SETLKW (struct flock *)
Wie für F_SETLK, aber bei Konflikten um eine Sperre auf die Datei wird auf die Freigabe der Sperre
gewartet. Falls während des Wartens ein Signal abgefangen wird, dann wird der Aufruf unterbrochen
und (nachdem der Signalbearbeiter zurückgekehrt ist) sofort zurückgekehrt (mit dem Rückgabewert -1
und errno auf EINTR gesetzt; siehe signal(7)).
F_GETLK (struct flock *)
Als Eingabe zu diesem Aufruf beschreibt lock eine Sperre, die auf diese Datei angewandt werden
soll. Falls die Sperre angewandt werden könnte, setzt fcntl() diese nicht wirklich, sondern
liefert F_UNLCK in dem Feld l_type von lock und lässt die anderen Felder dieser Struktur
unverändert.
Falls eine oder mehrere inkompatible Sperren das Setzen dieser Sperre verhinderten, dann liefert
fcntl() Details über eine dieser Sperren in den Feldern l_type, l_whence, l_start und l_len von
lock zurück. Falls die im Konflikt stehende Sperre eine traditionelle (Prozess-orientierte)
Datensatzsperre ist, dann wird das Feld l_pid auf die PID des Prozesses gesetzt, der die Sperre
hält. Falls die in Konflikt stehende Sperre eine offene Dateideskriptionssperre ist, dann wird
l_pid auf -1 gesetzt. Beachten Sie, dass die zurückgelieferte Information zum Zeitpunkt der
Analyse durch den Aufrufenden bereits veraltet sein kann.
Um eine Lesesperre zu setzen, muss dd zum Lesen offen sein. Um eine Schreibsperre zu setzen, muss dd zum
Schreiben offen sein. Um beide Typen setzen zu können, öffnen Sie eine Datei lese- und schreibbar.
Wenn Sperren mit F_SETLKW gesetzt werden, erkennt der Kernel Verklemmungen, bei denen zwei oder mehr
Prozesse ihre Sperr-Anfragen gegenseitig durch Sperren, die von anderen Prozessen gehalten werden,
blockieren. Nehmen Sie beispielsweise an, Prozess A hält eine Schreibsperre auf Byte 100 einer Datei und
Prozess B hält eine Schreibsperre auf Byte 200. Falls jeder Prozess dann versucht, mit F_SETLKW die vom
anderen Prozess bereits gesperrten Bytes zu sperren, würden ohne Erkennung von Verklemmungen beide
Prozesse unbegrenzt blockiert bleiben. Wenn der Kernel solche Verklemmungen erkennt, sorgt er dafür, dass
eine der blockierenden Sperranfragen sofort mit dem Fehler EDEADLK fehlschlägt. Eine Anwendung, die auf
einen solchen Fehler trifft, sollte einige ihrer Sperren freigeben, um anderen Anwendungen das Fortfahren
zu erlauben, bevor sie erneut versucht, die von ihr benötigten Sperren zu erlangen. Zirkuläre
Verklemmungen mit mehr als zwei Prozessen werden auch erkannt. Beachten Sie aber, dass es eine Begrenzung
der Erkennung von Verklemmungen im Kernel gibt; siehe FEHLER.
Datensatzsperren werden durch ein explizites F_UNLCK entfernt und auch freigegeben, wenn der Prozess sich
beendet.
Datensatzsperren werden nicht von einem durch fork(2) erstellten Kind geerbt, aber über ein execve(2)
hinweg erhalten.
Aufgrund des durch die stdio(3)-Bibliothek durchgeführten Pufferns sollte die Verwendung von
Datensatzsperren mit Routinen aus diesem Paket vermieden werden; verwenden Sie stattdessen read(2) und
write(2).
Die weiter oben beschriebenen Datensatzsperren werden dem Prozess zugeordnet (anders als die weiter unten
beschriebenen Dateideskriptionssperren). Dies hat einige unglückliche Konsequenzen:
• Falls ein Prozess irgendeinen Dateideskriptor mit Bezug zu einer Datei schließt, dann werden alle
Sperren des Prozesses für diese Datei aufgehoben, unabhängig von den Dateideskriptor(en), mit denen
diese Sperren erworben wurden. Das ist schlecht: Es bedeutet, dass ein Prozess seine Sperren auf eine
Datei wie /etc/passwd oder /etc/mtab verlieren kann, wenn aus irgendeinem Grund eine
Bibliotheksfunktion sich entscheidet, die gleiche Datei zu öffnen, zu lesen und zu schließen.
• Die Threads in einem Prozess nutzen die Sperren gemeinsam. Mit anderen Worten, ein Programm mit
mehreren Threads kann Datensatzsperren nicht benutzen, um sicherzustellen, dass die Threads nicht
simultan auf die gleichen Regionen einer Datei zugreifen.
Offene Dateideskriptionssperren lösen beide Probleme.
Offene Dateideskriptionssperren (nicht POSIX)
Offene Dateideskriptionsperren sind empfohlene Byte-Bereichssperren, deren Funktionsweise in den meisten
Aspekten den herkömmlichen, oben beschriebenen Datensatzsperren entspricht. Dieser Sperrtyp ist
Linux-spezifisch und seit Linux 3.15 verfügbar. (Es gibt einen Vorschlag der Austin-Gruppe, diesen
Sperrtyp in die nächste Überarbeitung von POSIX.1 aufzunehmen.) Eine Erklärung offener Dateideskriptionen
finden Sie in open(2).
Der Hauptunterschied zwischen den beiden Sperrtypen besteht darin, dass die herkömmlichen
Datensatzsperren mit einem Prozess verbunden sind, während Sperren offener Dateideskriptionen mit der
offenen Dateideskription verbunden sind, für die sie erlangt wurden, ähnlich wie Sperren, die mit
flock(2) erlangt wurden. Konsequenterweise (und anders als herkömmliche empfohlene Datensatzsperren)
werden Sperren offener Dateideskriptionen über fork(2) (und clone(2) mit CLONE_FILES) geerbt und werden
nur automatisch durch das Schließen der letzten offenen Dateideskription freigegeben, statt bei jedem
Schließen der Datei.
Im Konflikt stehende Kombinationen von Sperren (d.h. eine Lese-Sperre und eine Schreib-Sperre oder zwei
Schreib-Sperren), wobei eine Sperre eine offene Dateideskriptionssperre und die andere eine traditionelle
Datensatzsperre ist, sind selbst dann im Konflikt, wenn sie vom gleichen Prozess auf dem gleichen
Dateideskriptor aufgenommen wurden.
Offene Dateideskriptionssperren, die über die gleichen offenen Dateideskriptionen (d.h. über den gleichen
Dateideskriptor oder über durch fork(2), dup(2), fcntl() F_DUPFD und so weiter erstellte Duplikate des
Dateideskriptors) gesetzt werden, sind immer kompatibel: Falls auf einen bereits gesperrten Bereich eine
neue Sperre gesetzt wird, wird die existierende Sperre in den neuen Sperrtyp umgewandelt. (Solche
Umwandlungen können wie oben beschrieben zum Teilen, Verkleinern oder Verschmelzen mit einer
existierenden Sperre führen.)
Auf der anderen Seite können offene Dateideskriptionssperren zueinander im Konflikt stehen, wenn sie über
verschiedene offene Dateideskriptionen erlangt wurden. Daher können die Threads in einem Programm mit
mehreren Threads offene Dateideskriptionssperren dazu verwenden, um den Zugriff auf Dateiregionen zu
koordinieren, indem jeder Thread sein eigenes open(2) auf der Datei durchführt und die Sperren über den
entstehenden Dateideskriptor anwendet.
Wie bei herkömmlichen empfohlenen Sperren ist das dritte Argument für fcntl(), lock, ein Zeiger auf eine
flock-Struktur. Im Gegensatz zu herkömmlichen Datensatzsperren muss das Feld l_pid dieser Struktur bei
Verwendung der unterhalb beschriebenen Befehle auf Null gesetzt werden.
Die Befehle für den Umgang mit offenen Dateideskriptionssperren sind analog zu denen, die mit
traditionellen Sperren verwandt werden:
F_OFD_SETLK (struct flock *)
Erlangt eine offene Dateideskriptionssperre (wenn l_type F_RDLCK oder F_WRLCK ist) oder gibt eine
offene Dateideskriptionssperre frei (wenn l_type F_UNLCK ist), für die Bytes, die durch die Felder
l_whence, l_start und l_len festgelegt sind. Falls durch einen anderen Prozess eine im Konflikt
stehende Sperre gehalten wird, liefert der Aufruf -1 zurück und setzt errno auf EAGAIN.
F_OFD_SETLKW (struct flock *)
Wie bei F_OFD_SETLK, aber falls eine im Konflikt stehende Sperre auf der Datei gehalten wird, dann
wird auf die Freigabe dieser Sperre gewartet. Falls beim Warten ein Signal gefangen wird, dann
wird der Aufruf unterbrochen und (nachdem der Signal-Handler zurückgekehrt ist) sofort
zurückgekehrt (mit einem Rückgabewert -1 und errno auf EINTR gesetzt, siehe signal(7)).
F_OFD_GETLK (struct flock *)
Bei der Eingabe zu diesem Aufruf beschreibt lock eine offene Dateideskriptionssperre, die auf der
Datei gesetzt werden soll. Falls die Sperre gesetzt werden könnte, setzt sie fcntl() nicht
wirklich, sondern liefert im Feld l_type von lock F_UNLCK zurück und lässt die anderen Felder der
Struktur unverändert. Falls eine oder mehrere inkompatible Sperren das Setzen dieser Sperre
behinderten, werden die Details über eine dieser Sperren mittels lock, wie oben für F_GETLK
beschrieben, zurückgeliefert.
In der aktuellen Implementierung wird nicht auf Verklemmungen für offene Dateideskriptionssperren
geprüft. (Dies steht im Gegensatz zu den prozessorientierten Datensatzsperren, bei denen der Kernel eine
Erkennung von Verklemmungen durchführt.)
Pflichtsperren
Warnung: Die Linux-Implementierung der Pflichtsperren ist unzuverlässig. Siehe FEHLER unten. Aufgrund
dieser Fehler und der Tatsache, dass davon ausgegangen wird, dass diese Funktionalität wenig genutzt
wird, sind die Pflichtsperren seit Linux 4.5 eine optionale Funktionalität, die durch eine
Konfigurationsoption (CONFIG_MANDATORY_FILE_LOCKING) gesteuert werden. In Linux 5.15 und neuer wird diese
Funktionalität nicht mehr unterstützt.
Standardmäßig sind herkömmliche (prozessorientierte) und Sperren offener Dateideskriptionsdatensätze
empfohlene Sperren. Empfohlene Sperren werden nicht erzwungen und sind nur bei der Zusammenarbeit von
Prozessen nützlich.
Beide Sperrtypen können auch verpflichtend sein. Verpflichtende Sperren werden für alle Prozesse
durchgesetzt. Falls ein Prozess einen inkompatiblen Zugriff auf einen Dateibereich versucht (z.B. read(2)
oder write(2)), der eine inkompatible verpflichtende Sperre hat, dann hängt das Ergebnis davon ab, ob der
Schalter O_NONBLOCK für seine offene Dateideskription aktiviert ist. Falls der Schalter O_NONBLOCK nicht
aktiviert ist, wird der Systemaufruf blockiert, bis die Sperre entfernt oder in einen Modus umgewandelt
wurde, der mit dem Zugriff kompatibel ist. Falls der Schalter O_NONBLOCK aktiviert ist, wird der
Systemaufruf mit dem Fehler EAGAIN fehlschlagen.
Um verpflichtende Sperren zu verwenden, müssen verpflichtende Sperren sowohl auf dem Dateisystem, das die
zu sperrende Datei enthält, aktiviert werden als auch auf der Datei selbst. Verpflichtende Sperren werden
auf Dateisystemen mit der Option »-o mand« von mount(8) oder dem Schalter MS_MANDLOCK für mount(2)
aktiviert. Verpflichtende Sperren werden für eine Datei aktiviert, indem das Ausführrecht für die Datei
entfernt und das »set-group-ID«-Rechte-Bit aktiviert wird (siehe chmod(1) und chmod(2)).
Verpflichtende Sperren werden nicht durch POSIX spezifiziert. Einige andere Systeme unterstützen auch
verpflichtende Sperren, allerdings unterscheiden sich die Details zur Aktivierung zwischen den Systemen.
Verlorene Sperren
Wenn eine empfohlene Sperre auf einem Netzwerkdateisystem wie NFS erlangt wird, ist es möglich, dass die
Sperre verloren geht. Die kann aufgrund administrativer Aktionen auf dem Server oder aufgrund einer
Netzwerkeinteilung (d.h. einem Verlust der Netzverbindung mit dem Server) passieren, die so lange dauert,
dass der Server annimmt, dass der Client nicht mehr funktioniert.
Wenn das Dateisystem ermittelt, dass eine Sperre verloren gegangen ist, können zukünftige read(2)- oder
write(2)-Anfragen mit dem Fehler EIO fehlschlagen. Dieser Fehler wird beibehalten, bis die Sperre
entfernt oder der Dateideskriptor geschlossen wird. Seit Linux 3.12 passiert dies zumindest auf NFSv4
(einschließlich aller Unterversionen).
Einige UNIX-Versionen senden in diesen Fällen ein Signal (SIGLOST). Linux definiert dieses Signal nicht
und stellt keine asynchrone Benachrichtigung über verlorene Sperren bereit.
Signale verwalten
F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG und F_SETSIG werden zur Verwaltung der
E/A-Verfügbarkeitssignale verwandt:
F_GETOWN (void)
Liefert (als Funktionsergebnis) die Prozess- oder Prozessgruppenkennung zurück, die derzeit SIGIO-
und SIGURG-Signale für Ereignisse auf Dateideskriptor dd erhält. Prozesskennungen werden als
positive Werte, Prozessgruppenkennungen als negative Werte zurückgeliefert (siehe aber auch FEHLER
unten). arg wird ignoriert.
F_SETOWN (int)
Setzt die Prozesskennung oder Prozessgruppenkennung, die SIGIO- und SIGURG-Signale für Ereignisse
auf dem Dateideskriptor dd erhalten wird. Der Zielprozess oder die Zielprozessgruppe wird in arg
angegeben. Eine Prozesskennung wird als positiver, eine Prozessgruppenkennung wird als negativer
Wert angegeben. Häufig legt sich der aufrufende Prozess als der Eigentümer fest (d.h. arg wird als
getpid(2) angegeben).
Neben dem Setzen des Dateideskriptoreigentümers muss auch die Erzeugung von Signalen auf dem
Dateideskriptor aktiviert werden. Dies erfolgt durch den Befehl fcntl() F_SETFL, um den
Dateistatusschalter SIGIO zu setzen, immer wenn Ein- oder Ausgabe auf dem Dateideskriptor möglich
wird. Der Befehl fcntl() F_SETSIG kann zum Erhalt des Empfangs von Signalen neben SIGIO verwandt
werden.
Senden von Signalen an den durch F_SETOWN festgelegten Prozesseigner (Gruppe) unterliegt den
gleichen Rechteprüfungen wie sie in kill(2) beschrieben sind, wobei der sendende Prozess derjenige
ist, der F_SETOWN einsetzt (siehe aber FEHLER unten). Falls diese Rechteprüfung fehlschlägt, wird
das Signal ohne Rückmeldung verworfen. Hinweis: Die Aktion F_SETOWN notiert die Berechtigungen des
Aufrufenden zum Zeitpunkt des Aufrufs von fcntl() und es sind diese gespeicherten Berechtigungen,
die für die Rechteüberprüfung verwandt werden.
Falls der Dateideskriptor dd sich auf ein Socket bezieht, wählt F_SETOWN auch den Empfänger des
Signals SIGURG, das ausgeliefert wird, wenn Außerbanddaten beim Socket eintreffen, aus. (SIGURG
wird in jeder Situation gesandt, in der select(2) berichtete, dass das Socket eine
»außergewöhnliche Bedingung« habe.)
Das Folgende stimmte in Linux 2.6.x bis einschließlich Linux 2.6.11:
Falls in einem Prozess mit mehreren Threads, der mit einer Threading-Bibliothek läuft, die
Thread-Gruppen unterstützt (z.B. NPTL), ein von Null verschiedener Wert an F_SETSIG
übergeben wird, dann hat ein an F_SETOWN übergebener positiver Wert eine andere Bedeutung:
Statt eine Prozesskennung zu sein, die einen gesamten Prozess identifiziert, ist es eine
Thread-Kennung, die einen bestimmten Prozess innerhalb des Threads identifiziert.
Konsequenterweise kann es notwendig sein, F_SETOWN das Ergebnis von gettid(2) statt von
getpid(2) zu übergeben, um vernünftige Ergebnisse zu erhalten, wenn F_SETSIG benutzt wird.
(In aktuellen Linux-Threading-Implementierungen ist die Kennung des Haupt-Threads identisch
zu seiner Prozesskennung. Das bedeutet, dass ein Programm mit nur einem einzigen Thread in
diesem Szenario genauso gettid(2) oder getpid(2) verwenden kann.) Beachten Sie allerdings,
dass die Aussage in diesem Absatz nicht auf das Signal SIGURG für Außerbanddaten für ein
Socket zutrifft: Dieses Signal wird immer zu einem Prozess oder einer Prozessgruppe
gesandt, abhängig vom in F_SETOWN übergebenen Wert.
Das obige Verhalten wurde in Linux 2.6.12 versehentlich deaktiviert und wird nicht mehr
wiederhergestellt. Seit Linux 2.6.32 verwenden Sie F_SETOWN_EX, um die Signale SIGIO und SIGURG
auf einen bestimmten Thread anzuwenden.
F_GETOWN_EX (struct f_owner_ex *) (seit Linux 2.6.32)
Liefert die aktuellen Eigenschaften des Dateideskriptoreigentümers, wie sie von einer vorherigen
F_SETOWN_EX-Aktion definiert wurden, zurück. Die Information wird in der Struktur, auf die arg
zeigt, zurückgeliefert. Sie hat die folgende Form:
struct f_owner_ex {
int type;
pid_t pid;
};
Das Feld type wird einen der Werte F_OWNER_TID, F_OWNER_PID oder F_OWNER_PGRP enthalten. Das Feld
pid ist eine positive Ganzzahl, die die Thread-Kennung, Prozesskennung oder Prozessgruppenkennung
darstellt. Siehe F_SETOWN_EX für weitere Details.
F_SETOWN_EX (struct f_owner_ex *) (seit Linux 2.6.32)
Diese Aktion führt eine ähnliche Aufgabe wie F_SETOWN aus. Sie erlaubt dem Aufrufenden,
E/A-Verfügbarkeitssignale zu einem bestimmten Thread, Prozess oder einer Prozessgruppe zu
dirigieren. Der Aufrufende bestimmt das Ziel der Signale mittels arg, der ein Zeiger auf eine
Struktur f_owner_ex ist. Das Feld type hat einen der folgenden Werte, der definiert, wie pid
interpretiert wird:
F_OWNER_TID
Sendet das Signal an den Thread, dessen Thread-Kennung (der von den Aufrufen clone(2) oder
gettid(2) zurückgelieferte Wert) in pid festgelegt ist.
F_OWNER_PID
Sendet das Signal an den Prozess dessen ID in pid angegeben ist.
F_OWNER_PGRP
Sendet das Signal zu der Prozessgruppe, deren Kennung in pid festgelegt ist. (Beachten Sie,
dass anders als bei F_SETOWN, eine Prozessgruppenkennung hier als positiver Wert festgelegt
ist.)
F_GETSIG (void)
Liefert (als Funktionsergebnis) das Signal zurück, das gesendet wird, wenn Ein- oder Ausgabe
möglich wird. Ein Wert von Null bedeutet, dass SIGIO gesandt wird. Jeder andere Wert
(einschließlich SIGIO) ist stattdessen das gesandt Signal. In diesem Fall sind zusätzliche
Informationen im Signal-Handler verfügbar, falls er mit SA_SIGINFO installiert wurde. arg wird
ignoriert.
F_SETSIG (int)
Setzt das gesandte Signal, wenn Ein- oder Ausgabe möglich wird, auf den in arg angegebenen Wert.
Ein Wert von Null bedeutet, das Vorgabesignal SIGIO zu senden. Jeder andere Wert (einschließlich
SIGIO) ist das stattdessen zu sendende Signal und in diesem Fall sind zusätzliche Informationen im
Signal-Handler verfügbar, falls dieser mit SA_SIGINFO installiert wurde.
Durch Verwendung von F_SETSIG mit einem von Null verschiedenen Wert und Setzen von SA_SIGINFO für
den Signal-Handler (siehe sigaction(2)) werden Zusatzinformationen über E/A-Ereignisse an den
Handler in einer Struktur siginfo_t übergeben. Falls das Feld si_code anzeigt, dass die Quelle
SI_SIGIO ist, gibt das Feld si_fd den mit diesem Ereignis korrelierten Dateideskriptor zurück.
Andernfalls gibt es keine Anzeichen, welche Dateideskriptoren wartend sind und Sie sollten die
normalen Mechanismen (select(2), poll(2), read(2) mit gesetztem O_NONBLOCK usw.) verwenden, um
herauszufinden, welche Dateideskriptoren für E/A verfügbar sind.
Beachten Sie, dass der in si_fd bereitgestellte Dateideskriptor derjenige ist, der in der Aktion
F_SETSIG festgelegt wurde. Dies kann zu ungewöhnlichen Grenzfällen führen. Falls der
Dateideskriptor dupliziert wird (dup(2) oder ähnlich) und der ursprüngliche Dateideskriptor
geschlossen wird, dann werden E/A-Ereignisse weiterhin generiert aber das Feld si_fd wird die
Anzahl der jetzt geschlossenen Dateideskriptoren enthalten.
Durch Auswahl von Echtzeitsignalen (Wert >= SIGRTMIN), können mehrere E/A-Ereignisse unter
Verwendung der gleichen Signalnummer in eine Warteschlange eingereiht werden. (Einreihung in
Warteschlangen hängt vom verfügbaren Speicher ab). Falls wie oben SA_SIGINFO für den
Signal-Handler gesetzt ist, sind zusätzliche Informationen verfügbar.
Beachten Sie, dass Linux eine Begrenzung für die Anzahl der Echtzeitsignale erzwingt, die für
einen Prozess in eine Warteschlange eingereiht werden (siehe getrlimit(2) und signal(7)). Falls
diese Begrenzung erreicht ist, kehrt der Kernel zur Auslieferung von SIGIO zurück und dieses
Signal wird dem gesamten Prozess statt nur einem bestimmten Thread ausgeliefert.
Mittels dieser Mechanismen kann ein Programm eine komplett asynchrone E/A implementieren, ohne (in den
meisten Fällen) select(2) oder poll(2) zu verwenden.
Die Verwendung von O_ASYNC ist für BSD und Linux spezifisch. Die einzige in POSIX.1 spezifizierte
Verwendung von F_GETOWN and F_SETOWN ist im Zusammenhang mit der Verwendung des Signals SIGURG bei
Sockets. (POSIX spezifiziert das Signal SIGIO nicht). POSIX enthält asynchrone E/A und auch die Struktur
aio_sigevent, um ähnliche Dinge zu erreichen; diese sind unter Linux auch als Teil der GNU-C-Bibliothek
(Glibc) verfügbar.
Ausleihe
F_SETLEASE und F_GETLEASE (Linux 2.4 und neuer) werden dazu verwandt, für die offene Dateideskription,
auf den der Dateideskriptor dd verweist, eine Ausleihe (»lease«) zu etablieren und die aktuelle Ausleihe
zu ermitteln. Ein Datei-Ausleihe stellt einen Mechanismus bereit, durch den ein Prozess, der die Ausleihe
hält (der »Ausleiher«) über die Auslieferung eines Signals benachrichtigt wird, wenn ein Prozess (der
»Ausleihe-Brecher«) versucht, die von diesem Dateideskriptor referenzierte Datei mit open(2) zu öffen
oder mit truncate(2) zu verkleinern/vergrößern.
F_SETLEASE (int)
Setzt oder entfernt eine Datei-Ausleihe, abhängig davon, welcher der folgenden Wert in der
Ganzzahl arg angegeben ist:
F_RDLCK
Nimmt eine Lese-Ausleihe heraus. Dies führt dazu, dass der aufrufende Prozess informiert
wird, wenn die Datei zum Schreiben geöffnet oder abgeschnitten wird. Eine Lese-Ausleihe
kann nur auf einen Dateideskriptor gelegt werden, der nur-lesbar geöffnet ist.
F_WRLCK
Nimmt eine Schreibe-Ausleihe heraus. Dies führt dazu, dass der aufrufende Prozess
informiert wird, wenn die Datei zum Lesen oder Schreiben geöffnet oder abgeschnitten wird.
Eine Schreibe-Ausleihe kann nur auf eine Datei gelegt werden, falls es keine anderen
offenen Dateideskriptoren für diese Datei gibt.
F_UNLCK
Unsere Ausleihe von einer Datei entfernen.
Ausleihen sind einem offenen Dateideskriptor zugeordnet (siehe open(2)). Das bedeutet, dass ein
duplizierter Dateideskriptor (zum Beispiel durch fork(2) oder dup(2) erstellt) sich auf die gleiche
Ausleihe bezieht und dass diese Ausleihe durch jeden dieser Deskriptoren verändert oder freigegeben
werden kann. Desweiteren werden Ausleihen durch eine explizite Aktion F_UNLCK auf einem dieser
duplizierten Dateideskriptoren freigegeben oder wenn alle solchen Dateideskriptoren geschlossen wurden.
Ausleihen dürfen nur für reguläre Dateien herausgenommen werden. Ein nicht privilegierter Prozess darf
eine Ausleihe nur für Dateien herausnehmen, deren UID (Eigentümer) auf die Dateisystem-UID des Prozesses
passt. Ein Prozess mit der Capability CAP_LEASE darf Ausleihen für beliebige Dateien herausnehmen.
F_GETLEASE (void)
Zeigt den Typ der Ausleihe, der dem Dateideskriptor dd zugeordnet ist, an, indem entweder F_RDLCK,
F_WRLCK oder F_UNLCK zurückgeliefert wird, das respektive eine Lese-, Schreib- oder keine Ausleihe
anzeigt. arg wird ignoriert.
Wenn ein Prozess (der »Ausleihe-Brecher«) ein open(2) oder truncate(2) durchführt, der mit einer mittels
F_SETLEASE etablierten Ausleihe in Konflikt steht, wird der Systemaufruf durch den Kernel blockiert und
der Kernel informiert den Ausleihenden, indem er ihm ein Signal (standardmäßig SIGIO) sendet. Der
Ausleihende sollte reagieren, indem er alle notwendigen Aufräumarbeiten durchführt, um den Zugriff des
anderen Prozesses auf die Datei vorzubereiten (z.B. das Rausschreiben von zwischengespeicherten Puffern).
Danach sollte er entweder seine Ausleihe entfernen oder runterstufen. Eine Ausleihe wird durch Ausführung
des Befehls F_SETLEASE mit der Angabe von arg als F_UNLCK entfernt. Falls der Ausleihende derzeit eine
Schreib-Ausleihe auf die Datei hält und der Ausleih-Brecher die Datei zum Lesen öffnet, dann reicht es
aus, wenn der Ausleihende seine Ausleihe auf eine Lese-Ausleihe herunterstuft. Dies erfolgt durch
Ausführung des Befehls F_SETLEASE mit der Angabe von arg als F_RDLCK.
Falls der Ausleihende nicht innerhalb der in /proc/sys/fs/lease-break-time festgelegten Anzahl von
Sekunden seine Ausleihe herunterstuft oder entfernt, entfernt der Kernel die Ausleihe des Ausleihenden
zwangsweise oder stuft sie zwangsweise herunter.
Sobald ein Ausleih-Brechen eingeleitet wurde, liefert F_GETLEASE den Ziel-Ausleihtyp (entweder F_RDLCK
oder F_UNLCK, abhängig davon, was zum Ausleih-Brecher kompatibel wäre) zurück, bis der Ausleihende
freiwillig seine Ausleihe herunterstuft oder entfernt oder der Kernel dies zwangsweise tut, nachdem der
Ausleih-Brech-Timer abgelaufen ist.
Sobald die Ausleihe freiwillig oder zwangsweise entfernt oder heruntergestuft wurde und unter der
Annahme, dass der Ausleih-Brecher nicht den Systemaufruf entblockiert hat, erlaubt der Kernel dem
Systemaufruf des Ausleih-Brechers fortzufahren.
Falls das vom Ausleih-Brecher blockierte open(2) oder truncate(2) durch einen Signal-Handler unterbrochen
wird, schlägt der Systemaufruf mit dem Fehler EINTR fehl, aber die anderen Schritte erfolgen dennoch wie
oben beschrieben. Falls der Ausleih-Brecher durch ein Signal getötet wird, während er in open(2) oder
truncate(2) blockiert ist, erfolgen die anderen Schritte dennoch wie oben beschrieben. Falls der
Ausleih-Brecher den Schalter O_NONBLOCK beim Aufruf von open(2) angegeben hat, schlägt der Aufruf sofort
mit dem Fehler EWOULDBLOCK fehl, aber die anderen Schritte erfolgen dennoch wie oben beschrieben.
Standardmäßig wird das Signal SIGIO zur Information des Ausleihenden verwandt, dies kann aber mit dem
Befehl F_SETSIG von fcntl() geändert werden. Falls ein Befehl F_SETSIG ausgeführt wird (selbst einer, der
SIGIO festlegt) und der Singal-Handler mittels SA_SIGINFO etabliert wurde, dann wird der Handler eine
Struktur siginfo_t als sein zweites Argument erhalten und das Feld si_fd dieses Argumentes wird den
Dateideskriptor der Datei mit der Ausleihe, auf die ein anderer Prozess zugegriffen hat, enthalten. (Dies
ist nützlich, falls der Aufrufende Ausleihen für mehrere Dateien hält.)
Datei- und Verzeichnis-Änderungsbenachrichtigung (dnotify)
F_NOTIFY (int)
(Seit Linux 2.4) Stellt Benachrichtigungen bereit, wenn das durch dd referenzierte Verzeichnis
oder eine der darin enthaltenen Dateien geändert wird. Die Ereignisse, für die benachrichtigt
wird, werden in arg angegeben. Dies ist eine Bitmaske, in der mittels ODER eines oder mehrere der
folgenden Bits festgelegt sind:
DN_ACCESS
Ein Dateizugriff erfolgte (read(2), pread(2), readv(2) und ähnliche).
DN_MODIFY
Eine Datei wurde verändert (write(2), pwrite(2), writev(2), truncate(2), ftruncate(2) und
ähnliche).
DN_CREATE
Eine Datei wurde erstellt (open(2), creat(2), mknod(2), mkdir(2), link(2), symlink(2),
rename(2) in dieses Verzeichnis).
DN_DELETE
Der Link auf eine Datei wurde entfernt (unlink(2), rename(2) in ein anderes Verzeichnis,
rmdir(2)).
DN_RENAME
Eine Datei wurde innerhalb dieses Verzeichnis umbenannt (rename(2)).
DN_ATTRIB
Die Attribute einer Datei wurden geändert (chown(2), chmod(2), utime(2), utimensat(2) und
ähnliche).
(Um diese Definitionen zu erhalten, muss das Feature-Test-Makro _GNU_SOURCE vor der Einbindung
irgendeiner Header-Datei definiert werden.)
Verzeichnisbenachrichtigungen sind normalerweise »einmalig« und die Anwendung muss sich erneut
registrieren, um weitere Benachrichtigungen zu erhalten. Wird alternativ DN_MULTISHOT in arg
aufgenommen, bleiben die Benachrichtigungen aktiv, bis sie explizit entfernt werden.
Eine Reihe von F_NOTIFY-Anfragen ist kumulativ, bei der die Ereignisse in arg zu der Menge der
bereits beobachteten hinzugefügt werden. Um Benachrichtigungen für alle Ereignisse zu
deaktivieren, führen Sie einen Aufruf F_NOTIFY mit arg als 0 durch.
Benachrichtigungen erfolgen über die Zustellung eines Signals. Das Standardsignal ist SIGIO, dies
kann aber mittels des Befehls F_SETSIG von fcntl() geändert werden. (Beachten Sie, dass SIGIO
eines der nichtwarteschlangenfähigen Standardsignale ist; wird auf Echtzeitsignale umgestellt,
können mehrere Benachrichtigungen für den Prozess in die Warteschlange gestellt werden). Im
letzteren Falle erhält der Signal-Handler eine Struktur siginfo_t als zweites Argument (falls der
Hanndler mittels SA_SIGINFO etabliert wurde) und das Feld si_fd dieser Struktur enthält einen
Dateideskriptor, der die Benachrichtigung erstellte (nützlich, falls Benachrichtigungen für
mehrere Verzeichnisse eingerichtet werden).
Insbesondere bei der Verwendung von DN_MULTISHOT sollte ein Echtzeitsignal für die
Benachrichtigung verwandt werden, so dass mehrere Benachrichtigungen in die Warteschlange
aufgenommen werden können.
HINWEIS: Neue Anwendungen sollten die Schnittstelle inotify (verfügbar seit Linux 2.6.13)
verwenden, die eine deutlich überlegene Schnittstelle zur Ermittlung von Benachrichtigungen über
Dateisystemereignisse bietet. Siehe inotify(7).
Ändern der Kapazität einer Pipe
F_SETPIPE_SZ (int; seit Linux 2.6.35)
Ändert die Kapazität der durch dd referenzierten Pipe auf mindestens arg Byte. Ein
unprivilegierter Prozess kann die Pipe-Kapazität auf jeden Wert zwischen der Systemseitengröße und
der durch /proc/sys/fs/pipe-max-size (siehe proc(5)) definierten Grenze anpassen. Wird versucht,
die Pipe-Kapazität unter die Seitengröße zu setzen, dann wird diese ohne Rückmeldung auf die
Seitengröße gerundet. Versucht ein unprivilegierter Prozess, die Pipe-Kapazität über die in
/proc/sys/fs/pipe-max-size definierte Grenze zu setzen, führt dies zu dem Fehler EPERM; ein
privilegierter Prozess (CAP_SYS_RESOURCE) kann die Grenze außer Kraft setzen.
Beim Reservieren des Puffers für die Pipe darf der Kernel eine größere Kapazität als arg
verwenden, falls das für die Implementierung passend ist. (In der aktuellen Implementierung ist
die Allokation die nächst-größere Zweierpotenz des Vielfachen der Seitengröße der angeforderten
Größe.) Die tatsächliche gesetzte Kapazität (in Byte) wird als Ergebnis der Funktion
zurückgeliefert.
Wird versucht, die Pipe-Kapazität auf einen Wert zu setzen, der kleiner als der derzeit zum
Speichern von Daten verwandte Pufferbereich ist, dann wird der Fehler EBUSY erzeugt.
Beachten Sie, dass aufgrund der Art, wie die Seiten des Pipe-Puffers eingesetzt werden, wenn Daten
in die Pipe geschrieben werden, die Anzahl der Bytes geringer als die nominale Größe sein kann,
abhängig von der Größe der Schreibvorgänge.
F_GETPIPE_SZ (void; seit Linux 2.6.35)
Liefert (als Ergebnis der Funktion) die Kapazität der durch dd referenzierten Pipe zurück.
Versiegelung von Dateien
Dateisiegel begrenzen die Menge der erlaubten Aktionen für eine bestimmte Datei. Für jedes auf eine Datei
angebrachte Siegel wird von jetzt an eine bestimmte Gruppe an Aktionen auf dieser Datei mit dem Fehler
EPERM fehlschlagen. Die Datei wird als versiegelt bezeichnet. Die Vorgabemenge der Siegel hängt von der
Art der unterliegenden Datei und dem Dateisystem ab. Für einen Überblick über Dateiversiegelung, einer
Diskussion ihres Zwecks und Code-Beispiele siehe memfd_create(2).
Derzeit können Dateisiegel nur auf durch memfd_create(2) zurückgelieferte Dateideskriptoren angewandt
werden (falls MFD_ALLOW_SEALING eingesetzt wurde). Auf anderen Dateisystemen werden alle fcntl()-Aktionen
zur Versiegelung EINVAL zurückliefern.
Siegel sind eine Eigenschaft eines Inodes. Daher verfügen alle offenen Dateideskriptoren, die auf den
gleichen Inode verweisen, über die gleiche Gruppe an Siegeln. Desweiteren können Siegel nie entfernt, nur
hinzugefügt werden.
F_ADD_SEALS (int; seit Linux 3.17)
Fügt die im Bitmasken-Argument arg übergebenen Siegel zu der Gruppe der Siegel des Inodes, der vom
Dateideskriptor dd referenziert wird, hinzu. Siegel können nicht mehr entfernt werden. Sobald
dieser Aufruf gelingt, werden die Siegel sofort vom Kernel durchgesetzt. Falls die derzeitige
Gruppe der Siegel F_SEAL_SEAL enthält (siehe unten) wird dieser Aufruf mit EPERM abgelehnt.
Hinzufügen eines bereits gesetzten Siegels ist eine Nullaktion, falls F_SEAL_SEAL nicht bereits
gesetzt ist. Um ein Siegel zu setzen, muss der Dateideskriptor dd schreibbar sein.
F_GET_SEALS (void; seit Linux 3.17)
Liefert (als Funktionsergebnis) die aktuelle Menge der Siegel des durch dd referenzierten Inodes
zurück. Falls keine Siegel gesetzt sind, wird 0 zurückgeliefert. Falls die Datei Versiegelung
nicht unterstützt, wird -1 zurückgeliefert und errno auf EINVAL gesetzt.
Die folgenden Versiegelungen sind verfügbar:
F_SEAL_SEAL
Falls dieses Siegel gesetzt ist, wird jeder zukünftige Aufruf von fcntl() mit F_ADD_SEALS mit dem
Fehler EPERM fehlschlagen. Daher verhindert dieses Siegel jede Änderung an der Siegelmenge selbst.
Falls die ursprüngliche Siegelmenge einer Datei F_SEAL_SEAL enthält, dann führt dies effektiv
dazu, dass die Siegelmenge konstant und gesperrt ist.
F_SEAL_SHRINK
Falls dieses Siegel gesetzt ist, kann die in Frage kommende Datei nicht verkleinert werden. Dies
betrifft open(2) mit dem Schalter O_TRUNC sowie truncate(2) und ftruncate(2). Diese Aufrufe
schlagen mit EPERM fehl, falls Sie versuchen, die in Frage kommende Datei zu verkleinern.
Vergrößern der Datei ist weiterhin möglich.
F_SEAL_GROW
Falls dieses Siegel gesetzt ist, kann die in Frage kommende Datei nicht vergrößert werden. Dies
betrifft write(2) über das Ende der Datei hinaus, truncate(2), ftruncate(2) und fallocate(2).
Diese Aufrufe schlagen mit EPERM fehl, falls Sie versuchen, diese zum Vergrößern der Datei zu
verwenden. Falls Sie die Dateigröße beibehalten oder verkleinern, werden diese Aufrufe weiterhin
wie erwartet funktionieren.
F_SEAL_WRITE
Falls dieses Siegel gesetzt ist, können Sie den Inhalt der Datei nicht verändern. Beachten Sie,
dass das Verkleinern oder Vergrößern der Größe der Datei weiterhin möglich und erlaubt ist. Daher
wird dieses Siegel normalerweise zusammen mit einem der anderen Siegel verwandt. Dieses Siegel
betrifft write(2) und fallocate(2) (nur in Zusammenhang mit dem Schalter FALLOC_FL_PUNCH_HOLE).
Diese Aufrufe werden mit EPERM fehlschlagen, falls dieses Siegel gesetzt ist. Desweiteren wird das
Erstellen von gemeinsam benutzten schreibbaren Speicher-Mappings per mmap(2) auch mit EPERM
fehlschlagen.
Die Verwendung der Aktion F_ADD_SEALS zum Setzen von F_SEAL_WRITE wird mit EBUSY fehlschlagen,
falls irgendeine gemeinsam benutzbares schreibbares Speicher-Mappings existiert. Derartige
Mappings müssen vor dem Hinzufügen dieses Siegels aufgehoben werden. Weiterhin werden alle
ausstehenden Schreibvorgänge verworfen, falls irgendwelche asynchronen E/A-Transaktionen
(io_submit(2)) auf die Datei ausstehen.
F_SEAL_FUTURE_WRITE (seit Linux 5.1)
Die Wirkung dieses Siegels ist ähnlich zu F_SEAL_WRITE, aber der Inhalt der Datei kann weiterhin
mittels gemeinsamen schreibbaren Mappings, die vor dem Setzen des Siegels erstellt wurden,
verändert werden. Jeder Versuch, ein neues schreibbares Mapping auf der Datei mittels mmap(2) zu
erstellen, wird mit EPERM fehlschlagen. Entsprechend wird ein Versuch, in die Datei mit write(2)
zu schreiben, mit EPERM fehlschlagen.
Durch Einsatz dieses Siegels kann ein Prozess einen Speicherpuffer erstellen, den es weiterhin
verändern kann und der gleichzeitig von anderen Prozessen »nur lesend« mitgenutzt werden kann.
Datei Lese-/Schreibehinweise
Der Kernel kann mit Schreib-Lebenszeithinweisen über die erwartete relative Lebenszeit von
Schreibaktionen an einer benannten Inode oder über eine bestimmte offene Dateideskription informiert
werden (Siehe open(2) für eine Erläuterung von offenen Dateideskriptoren.). In diesem Kontext bedeutet
der Ausdruck »Schreib-Lebenszeit«, die erwartete Zeit, die die Daten auf dem Medium verbleiben, bevor sie
überschrieben oder gelöscht werden.
Eine Anwendung darf die unten angegebenen verschiedenen Hinweisewerte verwenden, um die Schreibaktionen
in verschiedene Schreibklassen zu trennen, so dass mehrere Benutzer oder Anwendungen, die mit dem
gleichen Speicher-Backend arbeiten, ihre E/A-Muster in einer konsistenten Art zusammenfassen können.
Allerdings implizieren diese Schalter keine funktionalen Semantiken und verschiedene E/A-Klassen können
die Schreib-Lebenszeithinweise in beliebigen Arten benutzen, so lange die Hinweise konsistent benutzt
werden.
Die folgenden Aktionen können auf den Dateideskriptor dd angewandt werden:
F_GET_RW_HINT (uint64_t *; seit Linux 4.13)
Liefert den Wert des Lese-/Schreibhinweises, der der durch dd referenzierten unterliegenden Inode
zugeordnet ist.
F_SET_RW_HINT (uint64_t *; seit Linux 4.13)
Setzt den Wert des Lese-/Schreibhinweises, der der durch dd referenzierten unterliegenden Inode
zugeordnet ist. Dieser Hinweis verbleibt, bis er entweder explizit geändert oder das unterliegende
Dateisystem ausgehängt wird.
F_GET_FILE_RW_HINT (uint64_t *; seit Linux 4.13)
Liefert den Wert des Lese-/Schreibhinweises, der der durch dd referenzierten offenen
Dateideskription zugeordnet ist.
F_SET_FILE_RW_HINT (uint64_t *; seit Linux 4.13)
Setzt den Wert des Lese-/Schreibhinweises, der der durch dd referenzierten offenen
Dateideskription zugeordnet ist.
Falls einer offenen Dateideskription noch kein Lese-/Schreibhinweis zugeordnet wurde, dann soll der der
Inode zugeordnete Wert verwandt werden, falls vorhanden.
Die folgenden Lese-/Schreibhinweise sind seit Linux 4.13 gültig:
RWH_WRITE_LIFE_NOT_SET
Es wurde kein spezieller Hinweis gesetzt. Dies ist der Vorgabewert.
RWH_WRITE_LIFE_NONE
Kein spezielle Schreib-Lebenszeit ist dieser Datei oder diesem Inode zugeordnet.
RWH_WRITE_LIFE_SHORT
Es wird erwartet, dass Daten, die in diese Inode oder über diesen offenen Dateideskriptor
geschrieben werden, eine kurze Lebenszeit haben werden.
RWH_WRITE_LIFE_MEDIUM
Es wird erwartet, dass Daten, die in diese Inode oder über diesen offenen Dateideskriptor
geschrieben werden, eine längere Lebenszeit als Daten, die mit RWH_WRITE_LIFE_SHORT geschrieben
wurden, haben werden.
RWH_WRITE_LIFE_LONG
Es wird erwartet, dass Daten, die in diese Inode oder über diesen offenen Dateideskriptor
geschrieben werden, eine längere Lebenszeit als Daten, die mit RWH_WRITE_LIFE_MEDIUM geschrieben
wurden, haben werden.
RWH_WRITE_LIFE_EXTREME
Es wird erwartet, dass Daten, die in diese Inode oder über diesen offenen Dateideskriptor
geschrieben werden, eine längere Lebenszeit als Daten, die mit RWH_WRITE_LIFE_LONG geschrieben
wurden, haben werden.
Alle schreibspezifischen Hinweise sind relativ zueinander und ihnen sollte keine individuelle absolute
Bedeutung beigemessen werden.
RÜCKGABEWERT
Für einen erfolgreichen Aufruf hängt der Rückgabewert von der Aktion ab:
F_DUPFD
Der neue Dateideskriptor.
F_GETFD
Wert des File-Deskriptor-Schalters.
F_GETFL
Wert der Dateistatusschalter.
F_GETLEASE
Art der Ausleihe, die auf dem Dateideskriptor gehalten wird.
F_GETOWN
Wert des Dateideskriptor-Eigentümers.
F_GETSIG
Wert des Signals, wenn Lesen oder Schreiben möglich wird, oder Null für traditionelles
SIGIO-Verhalten.
F_GETPIPE_SZ, F_SETPIPE_SZ
Die Kapazität der Pipe.
F_GET_SEALS
Eine Bitmaske, die die Siegel identifiziert, die für den durch dd referenzierten Inode gesetzt
wurden.
Alle anderen Befehle
Null
Bei einem Fehler wird -1 zurückgegeben und errno wird gesetzt, um den Fehler anzuzeigen.
FEHLER
EACCES oder EAGAIN
Aktion wird durch von anderen Prozessen gehaltene Sperren verhindert.
EAGAIN Die Aktion ist verboten, da die Datei durch einen anderen Prozess in den Speicher gemappt wurde.
EBADF dd ist kein offener Dateideskriptor.
EBADF Bef ist F_SETLK oder F_SETLKW und der Öffnungsmodus des Dateideskriptors passt nicht auf die
angeforderte Art der Sperre.
EBUSY Bef ist F_SETPIPE_SZ und die in arg angegebene neue Kapazität der Pipe ist kleiner als die Größe
des derzeit zur Speicherung von Daten in der Pipe verwandten Pufferspeichers.
EBUSY Bef ist F_ADD_SEALS, arg enthält F_SEAL_WRITE und es gibt ein schreibbares gemeinsam benutztes
Mapping der Datei, auf das dd verweist.
EDEADLK
Es wurde erkannt, dass der angegebene Befehl F_SETLKW zu einer Verklemmung führen würde.
EFAULT lock befindet sich außerhalb Ihres adressierbaren Adressraums.
EINTR Bef ist F_SETLKW oder F_OFD_SETLKW und die Aktion wurde durch ein Signal unterbrochen; siehe
signal(7).
EINTR Bef ist F_GETLK, F_SETLK, F_OFD_GETLK oder F_OFD_SETLK und die Aktion wurde durch ein Signal
unterbrochen, bevor die Sperre geprüft oder erworben werden konnte. Passiert am wahrscheinlichsten
beim Sperren von Dateien in der Ferne (d.h. Sperren über NFS), kann aber manchmal auch lokal
auftreten.
EINVAL Der in Bef angegebene Wert wird von diesem Kernel nicht erkannt.
EINVAL Bef ist F_ADD_SEALS und arg enthält ein nicht erkanntes Versiegelungs-Bit.
EINVAL Bef ist F_ADD_SEALS oder F_GET_SEALS und das Dateisystem, das den durch dd referenzierten Inode
enthält, unterstützt kein Versiegeln.
EINVAL Bef ist F_DUPFD und arg ist negativ oder ist größer als der maximal zulässige Wert (siehe die
Diskussion von RLIMIT_NOFILE in getrlimit(2)).
EINVAL Bef ist F_SETSIG und arg ist keine erlaubbare Signalnummer.
EINVAL Bef ist F_OFD_SETLK, F_OFD_SETLKW oder F_OFD_GETLK und l_pid wurde nicht als Null angegeben.
EMFILE Bef ist F_DUPFD und die Beschränkung pro Prozess für die Anzahl offener Dateideskriptoren wurde
erreicht.
ENOLCK Zu viele Segment-Sperren offen, die Sperr-Tabelle ist voll oder ein Sperrprotokoll aus der Ferne
schlug fehl (z.B. Sperren über NFS).
ENOTDIR
F_NOTIFY wurde in Bef angegeben, aber dd zeigt nicht auf ein Verzeichnis.
EPERM Bef ist F_SETPIPE_SZ und die weiche oder harte Benutzer-Pipe-Beschränkung wurde erreicht; siehe
pipe(7).
EPERM Es wurde versucht, den Schalter O_APPEND auf einer Datei zurückzusetzen, bei der das Attribut »nur
anhängen« gesetzt ist.
EPERM Bef war F_ADD_SEALS aber dd war nicht zum Schreiben offen oder die aktuelle Menge der Siegel der
Datei enthält bereits F_SEAL_SEAL.
STANDARDS
SVr4, 4.3BSD, POSIX.1-2001. Nur die Aktionen F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK,
F_SETLK und F_SETLKW sind in POSIX.1-2001 spezifiziert.
F_GETOWN und F_SETOWN sind in POSIX.1-2001 spezifiziert. (Um Ihre Definitionen zu erhalten, definieren
Sie entweder _XOPEN_SOURCE mit einem Wert größer oder gleich 500 oder definieren Sie _POSIX_C_SOURCE mit
einem Wert größer oder gleich 200809L.)
F_DUPFD_CLOEXEC ist in POSIX.1-2001 spezifiziert. (Um diese Definitionen zu erhalten, definieren Sie
_POSIX_C_SOURCE mit einem Wert größer oder gleich 200809L oder _XOPEN_SOURCE mit einem Wert größer oder
gleich 700.)
F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE und
F_SETLEASE sind Linux-spezifisch. (Definieren Sie das Makro _GNU_SOURCE, um diese Definitionen zu
erhalten.)
F_OFD_SETLK, F_OFD_SETLKW und F_OFD_GETLK sind Linux-spezifisch (und _GNU_SOURCE muss definiert werden,
um ihre Definitionen zu erhalten). Es wird aber daran gearbeitet, dass sie in der nächsten Version von
POSIX.1 enthalten sind.
F_ADD_SEALS und F_GET_SEALS sind Linux-spezifisch.
ANMERKUNGEN
Die Fehler, die von dup2(2) zurückgegeben werden, sind anders als die von F_DUPFD.
Sperrung von Dateien
Der ursprüngliche Systemaufruf fcntl() von Linux war nicht dafür konstruiert, große Dateiversätze (in der
Struktur flock) zu handhaben. Konsequenterweise wurde ein Systemaufruf fcntl64() in Linux 2.4
hinzugefügt. Dieser neuere Systemaufruf setzt eine andere Struktur zum Sperren von Dateien ein, flock64,
und entsprechende Befehle F_GETLK64, F_SETLK64 und F_SETLKW64. Diese Details können allerdings von
Anwendungen, die Glibc einsetzen, ignoriert werden, da dessen Wrapperfunktion fcntl() transparent den
neueren Systemaufruf einsetzt, wo er verfügbar ist.
Datensatzsperren
Seit Linux 2.0 gibt es keine Wechselwirkung zwischen den durch flock(2) und fcntl() gesetzten Sperrtypen.
Bei einer Reihe von Systemen gibt es in struct flock weitere Felder wie z.B. l_sysid (zur Identifizierung
der Maschine, auf der die Sperre gehalten wird). Es ist klar, dass l_pid alleine nicht sehr nützlich ist,
falls der Prozess, der die Sperre hält, auf einer anderen Maschine existiert. Unter Linux wird dieses
Feld, auch wenn es auf einigen Architekturen (wie MIPS32) vorhanden ist, nicht verwandt.
Der ursprüngliche Systemaufruf fcntl() von Linux war nicht dafür konstruiert, große Dateiversätze (in der
Struktur flock) zu handhaben. Konsequenterweise wurde ein Systemaufruf fcntl64() in Linux 2.4
hinzugefügt. Dieser neuere Systemaufruf setzt eine andere Struktur zum Sperren von Dateien ein, flock64,
und entsprechende Befehle F_GETLK64, F_SETLK64 und F_SETLKW64. Diese Details können allerdings von
Anwendungen, die Glibc einsetzen, ignoriert werden, da dessen Wrapperfunktion fcntl() transparent den
neueren Systemaufruf einsetzt, wo er verfügbar ist.
Datensatzsperren und NFS
Falls ein NFSv4-Client vor Linux 3.12 den Kontakt mit dem Server für eine bestimmte Zeitperiode
(definiert als mehr als 90 Sekunden ohne Kommunikation) verlor, konnte er eine Sperre verlieren und
wieder erlangen, ohne von dieser Tatsache Kenntnis zu erhalten. (Die Zeitperiode, nach der der Kontakt
als verloren angesehen wird, ist als NFSv4-Ausleihzeit bekannt. Auf einem Linux-NFS-Server kann diese
durch einen Blick in /proc/fs/nfsd/nfsv4leasetime, die diese Periode in Sekunden ausdrückt, bestimmt
werden. Der Vorgabewert für diese Datei ist 90.) In diesem Szenario sind potenziell Datenbeschädigungen
möglich, da ein anderer Prozess in der Zwischenzeit eine Sperre erlangen und Datei-E/A durchführen
könnte.
Wenn seit Linux 3.12 ein NFSv4-Client den Kontakt mit dem Server verliert, wird jede E/A des Prozesses,
der »glaubt«, er halte eine Sperre, fehlschlagen, bis dieser Prozess die Datei schließt und erneut
öffnet. Ein Kernelparameter (nfs.recover_lost_locks) kann auf 1 gesetzt werden, um das pre-3.12-Verhalten
zu erreichen, bei dem ein Client versuchen wird, verloren gegangene Sperren wiederherzustellen, wenn der
Kontakt mit dem Server wieder etabliert ist. Aufgrund des vorhandenen Risikos der Datenverfälschung ist
die Vorgabe für diesen Parameter 0 (deaktiviert).
FEHLER
F_SETFL
Es ist nicht möglich, F_SETFL zum Ändern des Zustands der Schalter O_DSYNC und O_SYNC zu verwenden.
Versuche, den Zustand dieser Schalter zu ändern, werden ohne Meldung ignoriert.
F_GETOWN
Eine Begrenzung der Linux-Systemaufrufkonventionen auf einigen Architekturen (insbesondere i386)
bedeutet, dass, falls eine von F_GETOWN zurückgelieferte (negative) Prozessgruppenkennung in den Bereich
-1 bis -4095 fällt, dies von Glibc fälschlicherweise als Fehler im Systemaufruf interpretiert wird. Dann
wird der Rückgabewert von fcntl() -1 sein und errno wird die (positive) Prozessgruppenkennung enthalten.
Die Linux-spezifische Aktion F_GETOWN_EX vermeidet dieses Problem. Seit Glibc 2.11 versteckt Glibc das
Kernelproblem F_GETOWN, indem F_GETOWN mittels F_GETOWN_EX implementiert wird.
F_SETOWN
Unter Linux 2.4 und älter gibt es einen Fehler, der auftreten kann, wenn ein unprivilegierter Prozess
statt einem Aufrufenden F_SETOWN verwendet, um den Eigentümer eines Socket-Dateideskriptors als
Prozess(gruppe) festzulegen. In diesem Fall kann fcntl() -1 mit errno auf EPERM gesetzt zurückliefern,
selbst wenn der/die Eigentümerprozess(gruppe) dergestalt ist, dass der Aufrufende Rechte hat, ihr/ihm
Signale zu senden. Trotz dieses zurückgelieferten Fehlers wird der Dateieigentümer gesetzt und Signale
werden zum Eigentümer gesandt.
Erkennung von Verklemmungen
Der vom Kernel eingesetzte Algorithmus zur Erkennung von Verklemmungen beim Umgang mit F_SETLKW kann
sowohl falsch-negative (keine Erkennung von Verklemmungen, eine Gruppe von verklemmten Prozessen bleibt
unbegrenzt blockiert) als auch falsch-positive (EDEADLK-Fehler obwohl keine Verklemmung vorliegt)
liefern. Beispielsweise begrenzt der Kernel die Sperrtiefe seiner Abhängigkeitssuche auf 10 Schritte, was
bedeutet, dass zirkulare Verklemmungsketten, die diese Größe überschreiten, nicht erkannt werden.
Zusätzlich kann der Kernel fälschlicherweise eine Verklemmung erkennen, wenn zwei oder mehr Prozesse, die
mit dem Schalter CLONE_FILES von clone(2) Sperren setzen, die (dem Kernel) als im Konflikt stehend
erscheinen.
Pflichtsperren
Die Linux-Implementierung von Pflichtsperren ist Gegenstand von Ressourcenwettläufen, die sie
unzuverlässig machen: Ein write(2)-Aufruf, der sich mit einer Sperre überschneidet, kann Daten verändern,
nachdem die Pflichtsperre erlangt wurde. Ein read(2)-Aufruf, der sich mit einer Sperre überschneidet,
kann Änderungen an Daten entdecken, die nur vorgenommen wurden, nachdem eine Schreibsperre erlangt wurde.
Ähnliche Wettläufe gibt es zwischen Pflichtsperren und mmap(2). Daher ist es nicht zu empfehlen, sich auf
Pflichtsperren zu verlassen.
SIEHE AUCH
dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7), lslocks(8)
locks.txt, mandatory-locking.txt und dnotify.txt in dem Linux-Kernelquelldateiverzeichnis
Documentation/filesystems/. (Bei älteren Kerneln befinden sich diese Dateien direkt unter dem Verzeichnis
Documentation/ und mandatory-locking.txt heißt mandatory.txt.)
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Schulze <joey@infodrom.org>, Chris Leick
<c.leick@vollbio.de>, Helge Kreutzmann <debian@helgefjell.de> und Mario Blättermann
<mario.blaettermann@gmail.com> 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 die
Mailingliste der Übersetzer.
Linux man-pages 6.03 5. Februar 2023 fcntl(2)