fcntl(2) System Calls Manual fcntl(2) BEZEICHNUNG fcntl - Dateideskriptoren manipulieren BIBLIOTHEK Standard-C-Bibliothek (libc, -lc) UBERSICHT #include int fcntl(int dd, int Bef, /* arg */ ); BESCHREIBUNG fcntl() fuhrt 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 benotigte Argumenttyp wird nach jedem Bef-Namen in Klammern angedeutet (in den meisten Fallen ist der benotigte Typ int und der Argumenttyp wird mit dem Namen arg identifiziert). Falls das Argument nicht notwendig ist, wird void angegeben. Bestimmte der unten aufgefuhrten Aktionen werden nur seit einer bestimmten Linux-Kernelversion unterstutzt. Die bevorzugte Methode, um herauszufinden, ob der Gastkernel eine bestimmte Aktion unterstutzt, ist der Aufruf von fcntl() mit dem gewunschten Wert von Bef und dem anschliessenden Test, ob der Aufruf mit EINVAL fehlschlug, wodurch angezeigt wird, dass der Kernel diesen Wert nicht unterstutzt. Duplizieren eines Dateideskriptors F_DUPFD (int) verdoppelt den Dateideskriptor dd unter Verwendung des Dateideskriptors mit der kleinsten Nummer, die identisch zu oder grosser als arg ist. Dies unterscheidet sich von dup2(2), das exakt den angegebenen Dateideskriptor verwendet. Bei Erfolg wird der neue Dateideskriptor zuruckgegeben. Lesen Sie dup(2) fur weitere Details. F_DUPFD_CLOEXEC (int; seit Linux 2.6.24) Wie fur F_DUPFD, setzt aber zusatzlich den Schalter >>close-on-exec<< fur den duplizierten Dateideskriptor. Die Angabe dieses Schalters ermoglicht es einem Programm, eine zusatzliche fcntl()-F_SETFD-Aktion zu vermeiden, um den Schalter FD_CLOEXEC zu setzen. Fur eine Erlauterung, warum dieser Schalter nutzlich ist, lesen Sie die Beschreibung von O_CLOEXEC in open(2). Datei-Deskriptor-Schalter Die folgenden Befehle verandern 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) fehlschlagt, bleibt der Dateideskriptor offen.) Falls das Bit FD_CLOEXEC nicht gesetzt ist, wird der Dateideskriptor uber 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) ausfuhrt, anfallig fur einen Ressourcenwettlauf, der unbeabsichtigterweise den Dateideskriptor an das Programm, das im Kindprozess lauft, durchsickern lasst. Siehe die Diskussion des Schalters O_CLOEXEC in open(2) fur Details und wie dem Problem abgeholfen werden kann. Dateistatusschalter Jede offene Dateideskription hat bestimmte zugeordnete Statusschalter, die durch open(2) initialisiert und moglicherweise durch fcntl() verandert 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 andern. Es ist nicht moglich, die Schalter O_DSYNC und O_SYNC zu andern, siehe FEHLER weiter unten. Empfohlene Datensatzsperren Linux implementiert traditionelle (>>Prozess-orientierte<<) UNIX-Datensatz-Sperren, wie durch POSIX standardisiert. Fur eine Linux-spezifische Alternative mit besserer Semantik lesen Sie die Diskussion uber 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 prufen. Das dritte Argument, lock, ist ein Zeiger auf eine Struktur, die mindestens die folgende Felder (in einer nicht festgelegten Reihenfolge) enthalt: 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 fur 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 konnen gesperrt sein, aber Bytes vor dem Anfang der Datei sind es nicht. l_start ist der Startversatz fur 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 abschliessenden zwei Fallen 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 einschliesslich l_start+l_len-1 umfassen. Die Angabe von 0 fur l_len hat eine besondere Bedeutung: Alle Bytes beginnend bei l_whence und l_start bis zum Ende der Datei sperren, unabhangig davon, wie gross die Datei anwachst. POSIX.1-2001 erlaubt (verlangt es aber nicht), dass eine Implementierung einen negativen Wert fur l_len unterstutzt. Falls l_len negativ ist, deckt das durch lock beschriebene Intervall die Bytes l_start+l_len bis zu einschliesslich l_start-1 ab. Dies wird durch Linux seit 2.4.21 und 2.5.49 unterstutzt. 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 konnen 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 zusammenfallt.) F_SETLK (struct flock *) Erlangt (wenn l_type F_RDLCK oder F_WRLCK ist) oder gibt eine Sperre (wenn l_type F_UNLCK ist) fur 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 zuruck und setzt errno auf EACCES oder EAGAIN. (Der in diesem Fall zuruckgelieferte Fehler unterscheidet sich zwischen Implementierungen, daher verlangt POSIX, dass portable Anwendungen auf beide Fehler prufen.) F_SETLKW (struct flock *) Wie fur F_SETLK, aber bei Konflikten um eine Sperre auf die Datei wird auf die Freigabe der Sperre gewartet. Falls wahrend des Wartens ein Signal abgefangen wird, dann wird der Aufruf unterbrochen und (nachdem der Signalbearbeiter zuruckgekehrt ist) sofort zuruckgekehrt (mit dem Ruckgabewert -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 konnte, setzt fcntl() diese nicht wirklich, sondern liefert F_UNLCK in dem Feld l_type von lock und lasst die anderen Felder dieser Struktur unverandert. Falls eine oder mehrere inkompatible Sperren das Setzen dieser Sperre verhinderten, dann liefert fcntl() Details uber eine dieser Sperren in den Feldern l_type, l_whence, l_start und l_len von lock zuruck. 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 halt. Falls die in Konflikt stehende Sperre eine offene Dateideskriptionssperre ist, dann wird l_pid auf -1 gesetzt. Beachten Sie, dass die zuruckgelieferte 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 konnen, offnen 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 halt eine Schreibsperre auf Byte 100 einer Datei und Prozess B halt eine Schreibsperre auf Byte 200. Falls jeder Prozess dann versucht, mit F_SETLKW die vom anderen Prozess bereits gesperrten Bytes zu sperren, wurden ohne Erkennung von Verklemmungen beide Prozesse unbegrenzt blockiert bleiben. Wenn der Kernel solche Verklemmungen erkennt, sorgt er dafur, dass eine der blockierenden Sperranfragen sofort mit dem Fehler EDEADLK fehlschlagt. 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 benotigten Sperren zu erlangen. Zirkulare 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 uber ein execve(2) hinweg erhalten. Aufgrund des durch die stdio(3)-Bibliothek durchgefuhrten 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 ungluckliche Konsequenzen: o Falls ein Prozess irgendeinen Dateideskriptor mit Bezug zu einer Datei schliesst, dann werden alle Sperren des Prozesses fur diese Datei aufgehoben, unabhangig 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 offnen, zu lesen und zu schliessen. o 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 losen beide Probleme. Offene Dateideskriptionssperren (nicht POSIX) Offene Dateideskriptionsperren sind empfohlene Byte-Bereichssperren, deren Funktionsweise in den meisten Aspekten den herkommlichen, oben beschriebenen Datensatzsperren entspricht. Dieser Sperrtyp ist Linux-spezifisch und seit Linux 3.15 verfugbar. (Es gibt einen Vorschlag der Austin-Gruppe, diesen Sperrtyp in die nachste Uberarbeitung von POSIX.1 aufzunehmen.) Eine Erklarung offener Dateideskriptionen finden Sie in open(2). Der Hauptunterschied zwischen den beiden Sperrtypen besteht darin, dass die herkommlichen Datensatzsperren mit einem Prozess verbunden sind, wahrend Sperren offener Dateideskriptionen mit der offenen Dateideskription verbunden sind, fur die sie erlangt wurden, ahnlich wie Sperren, die mit flock(2) erlangt wurden. Konsequenterweise (und anders als herkommliche empfohlene Datensatzsperren) werden Sperren offener Dateideskriptionen uber fork(2) (und clone(2) mit CLONE_FILES) geerbt und werden nur automatisch durch das Schliessen der letzten offenen Dateideskription freigegeben, statt bei jedem Schliessen 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 uber die gleichen offenen Dateideskriptionen (d.h. uber den gleichen Dateideskriptor oder uber 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 konnen wie oben beschrieben zum Teilen, Verkleinern oder Verschmelzen mit einer existierenden Sperre fuhren.) Auf der anderen Seite konnen offene Dateideskriptionssperren zueinander im Konflikt stehen, wenn sie uber verschiedene offene Dateideskriptionen erlangt wurden. Daher konnen 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 durchfuhrt und die Sperren uber den entstehenden Dateideskriptor anwendet. Wie bei herkommlichen empfohlenen Sperren ist das dritte Argument fur fcntl(), lock, ein Zeiger auf eine flock-Struktur. Im Gegensatz zu herkommlichen Datensatzsperren muss das Feld l_pid dieser Struktur bei Verwendung der unterhalb beschriebenen Befehle auf Null gesetzt werden. Die Befehle fur 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), fur 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 zuruck 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 zuruckgekehrt ist) sofort zuruckgekehrt (mit einem Ruckgabewert -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 konnte, setzt sie fcntl() nicht wirklich, sondern liefert im Feld l_type von lock F_UNLCK zuruck und lasst die anderen Felder der Struktur unverandert. Falls eine oder mehrere inkompatible Sperren das Setzen dieser Sperre behinderten, werden die Details uber eine dieser Sperren mittels lock, wie oben fur F_GETLK beschrieben, zuruckgeliefert. In der aktuellen Implementierung wird nicht auf Verklemmungen fur offene Dateideskriptionssperren gepruft. (Dies steht im Gegensatz zu den prozessorientierten Datensatzsperren, bei denen der Kernel eine Erkennung von Verklemmungen durchfuhrt.) Pflichtsperren Warnung: Die Linux-Implementierung der Pflichtsperren ist unzuverlassig. Siehe FEHLER unten. Aufgrund dieser Fehler und der Tatsache, dass davon ausgegangen wird, dass diese Funktionalitat wenig genutzt wird, sind die Pflichtsperren seit Linux 4.5 eine optionale Funktionalitat, die durch eine Konfigurationsoption (CONFIG_MANDATORY_FILE_LOCKING) gesteuert werden. In Linux 5.15 und neuer wird diese Funktionalitat nicht mehr unterstutzt. Standardmassig sind herkommliche (prozessorientierte) und Sperren offener Dateideskriptionsdatensatze empfohlene Sperren. Empfohlene Sperren werden nicht erzwungen und sind nur bei der Zusammenarbeit von Prozessen nutzlich. Beide Sperrtypen konnen auch verpflichtend sein. Verpflichtende Sperren werden fur 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 hangt das Ergebnis davon ab, ob der Schalter O_NONBLOCK fur 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, mussen verpflichtende Sperren sowohl auf dem Dateisystem, das die zu sperrende Datei enthalt, 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 fur mount(2) aktiviert. Verpflichtende Sperren werden fur eine Datei aktiviert, indem das Ausfuhrrecht fur 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 unterstutzen 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 moglich, 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, konnen zukunftige 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 (einschliesslich aller Unterversionen). Einige UNIX-Versionen senden in diesen Fallen ein Signal (SIGLOST). Linux definiert dieses Signal nicht und stellt keine asynchrone Benachrichtigung uber 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-Verfugbarkeitssignale verwandt: F_GETOWN (void) Liefert (als Funktionsergebnis) die Prozess- oder Prozessgruppenkennung zuruck, die derzeit SIGIO- und SIGURG-Signale fur Ereignisse auf Dateideskriptor dd erhalt. Prozesskennungen werden als positive Werte, Prozessgruppenkennungen als negative Werte zuruckgeliefert (siehe aber auch FEHLER unten). arg wird ignoriert. F_SETOWN (int) Setzt die Prozesskennung oder Prozessgruppenkennung, die SIGIO- und SIGURG-Signale fur 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. Haufig legt sich der aufrufende Prozess als der Eigentumer fest (d.h. arg wird als getpid(2) angegeben). Neben dem Setzen des Dateideskriptoreigentumers 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 moglich 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 Rechteprufungen wie sie in kill(2) beschrieben sind, wobei der sendende Prozess derjenige ist, der F_SETOWN einsetzt (siehe aber FEHLER unten). Falls diese Rechteprufung fehlschlagt, wird das Signal ohne Ruckmeldung verworfen. Hinweis: Die Aktion F_SETOWN notiert die Berechtigungen des Aufrufenden zum Zeitpunkt des Aufrufs von fcntl() und es sind diese gespeicherten Berechtigungen, die fur die Rechteuberprufung verwandt werden. Falls der Dateideskriptor dd sich auf ein Socket bezieht, wahlt F_SETOWN auch den Empfanger des Signals SIGURG, das ausgeliefert wird, wenn Ausserbanddaten beim Socket eintreffen, aus. (SIGURG wird in jeder Situation gesandt, in der select(2) berichtete, dass das Socket eine >>aussergewohnliche Bedingung<< habe.) Das Folgende stimmte in Linux 2.6.x bis einschliesslich Linux 2.6.11: Falls in einem Prozess mit mehreren Threads, der mit einer Threading-Bibliothek lauft, die Thread-Gruppen unterstutzt (z.B. NPTL), ein von Null verschiedener Wert an F_SETSIG ubergeben wird, dann hat ein an F_SETOWN ubergebener 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 ubergeben, um vernunftige 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 fur Ausserbanddaten fur ein Socket zutrifft: Dieses Signal wird immer zu einem Prozess oder einer Prozessgruppe gesandt, abhangig vom in F_SETOWN ubergebenen 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 Dateideskriptoreigentumers, wie sie von einer vorherigen F_SETOWN_EX-Aktion definiert wurden, zuruck. Die Information wird in der Struktur, auf die arg zeigt, zuruckgeliefert. 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 fur weitere Details. F_SETOWN_EX (struct f_owner_ex *) (seit Linux 2.6.32) Diese Aktion fuhrt eine ahnliche Aufgabe wie F_SETOWN aus. Sie erlaubt dem Aufrufenden, E/A-Verfugbarkeitssignale 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) zuruckgelieferte 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 zuruck, das gesendet wird, wenn Ein- oder Ausgabe moglich wird. Ein Wert von Null bedeutet, dass SIGIO gesandt wird. Jeder andere Wert (einschliesslich SIGIO) ist stattdessen das gesandt Signal. In diesem Fall sind zusatzliche Informationen im Signal-Handler verfugbar, falls er mit SA_SIGINFO installiert wurde. arg wird ignoriert. F_SETSIG (int) Setzt das gesandte Signal, wenn Ein- oder Ausgabe moglich wird, auf den in arg angegebenen Wert. Ein Wert von Null bedeutet, das Vorgabesignal SIGIO zu senden. Jeder andere Wert (einschliesslich SIGIO) ist das stattdessen zu sendende Signal und in diesem Fall sind zusatzliche Informationen im Signal-Handler verfugbar, falls dieser mit SA_SIGINFO installiert wurde. Durch Verwendung von F_SETSIG mit einem von Null verschiedenen Wert und Setzen von SA_SIGINFO fur den Signal-Handler (siehe sigaction(2)) werden Zusatzinformationen uber E/A-Ereignisse an den Handler in einer Struktur siginfo_t ubergeben. Falls das Feld si_code anzeigt, dass die Quelle SI_SIGIO ist, gibt das Feld si_fd den mit diesem Ereignis korrelierten Dateideskriptor zuruck. 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 fur E/A verfugbar sind. Beachten Sie, dass der in si_fd bereitgestellte Dateideskriptor derjenige ist, der in der Aktion F_SETSIG festgelegt wurde. Dies kann zu ungewohnlichen Grenzfallen fuhren. Falls der Dateideskriptor dupliziert wird (dup(2) oder ahnlich) und der ursprungliche 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), konnen mehrere E/A-Ereignisse unter Verwendung der gleichen Signalnummer in eine Warteschlange eingereiht werden. (Einreihung in Warteschlangen hangt vom verfugbaren Speicher ab). Falls wie oben SA_SIGINFO fur den Signal-Handler gesetzt ist, sind zusatzliche Informationen verfugbar. Beachten Sie, dass Linux eine Begrenzung fur die Anzahl der Echtzeitsignale erzwingt, die fur 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 zuruck 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 Fallen) select(2) oder poll(2) zu verwenden. Die Verwendung von O_ASYNC ist fur 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 enthalt asynchrone E/A und auch die Struktur aio_sigevent, um ahnliche Dinge zu erreichen; diese sind unter Linux auch als Teil der GNU-C-Bibliothek (Glibc) verfugbar. Ausleihe F_SETLEASE und F_GETLEASE (Linux 2.4 und neuer) werden dazu verwandt, fur 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 halt (der >>Ausleiher<<) uber die Auslieferung eines Signals benachrichtigt wird, wenn ein Prozess (der >>Ausleihe-Brecher<<) versucht, die von diesem Dateideskriptor referenzierte Datei mit open(2) zu offen oder mit truncate(2) zu verkleinern/vergrossern. F_SETLEASE (int) Setzt oder entfernt eine Datei-Ausleihe, abhangig davon, welcher der folgenden Wert in der Ganzzahl arg angegeben ist: F_RDLCK Nimmt eine Lese-Ausleihe heraus. Dies fuhrt dazu, dass der aufrufende Prozess informiert wird, wenn die Datei zum Schreiben geoffnet oder abgeschnitten wird. Eine Lese-Ausleihe kann nur auf einen Dateideskriptor gelegt werden, der nur-lesbar geoffnet ist. F_WRLCK Nimmt eine Schreibe-Ausleihe heraus. Dies fuhrt dazu, dass der aufrufende Prozess informiert wird, wenn die Datei zum Lesen oder Schreiben geoffnet oder abgeschnitten wird. Eine Schreibe-Ausleihe kann nur auf eine Datei gelegt werden, falls es keine anderen offenen Dateideskriptoren fur 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 verandert 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 durfen nur fur regulare Dateien herausgenommen werden. Ein nicht privilegierter Prozess darf eine Ausleihe nur fur Dateien herausnehmen, deren UID (Eigentumer) auf die Dateisystem-UID des Prozesses passt. Ein Prozess mit der Capability CAP_LEASE darf Ausleihen fur 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 zuruckgeliefert 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) durchfuhrt, 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 (standardmassig SIGIO) sendet. Der Ausleihende sollte reagieren, indem er alle notwendigen Aufraumarbeiten durchfuhrt, 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 Ausfuhrung des Befehls F_SETLEASE mit der Angabe von arg als F_UNLCK entfernt. Falls der Ausleihende derzeit eine Schreib-Ausleihe auf die Datei halt und der Ausleih-Brecher die Datei zum Lesen offnet, dann reicht es aus, wenn der Ausleihende seine Ausleihe auf eine Lese-Ausleihe herunterstuft. Dies erfolgt durch Ausfuhrung 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, abhangig davon, was zum Ausleih-Brecher kompatibel ware) zuruck, 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, schlagt der Systemaufruf mit dem Fehler EINTR fehl, aber die anderen Schritte erfolgen dennoch wie oben beschrieben. Falls der Ausleih-Brecher durch ein Signal getotet wird, wahrend 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, schlagt der Aufruf sofort mit dem Fehler EWOULDBLOCK fehl, aber die anderen Schritte erfolgen dennoch wie oben beschrieben. Standardmassig wird das Signal SIGIO zur Information des Ausleihenden verwandt, dies kann aber mit dem Befehl F_SETSIG von fcntl() geandert werden. Falls ein Befehl F_SETSIG ausgefuhrt 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 nutzlich, falls der Aufrufende Ausleihen fur mehrere Dateien halt.) Datei- und Verzeichnis-Anderungsbenachrichtigung (dnotify) F_NOTIFY (int) (Seit Linux 2.4) Stellt Benachrichtigungen bereit, wenn das durch dd referenzierte Verzeichnis oder eine der darin enthaltenen Dateien geandert wird. Die Ereignisse, fur 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 ahnliche). DN_MODIFY Eine Datei wurde verandert (write(2), pwrite(2), writev(2), truncate(2), ftruncate(2) und ahnliche). 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 geandert (chown(2), chmod(2), utime(2), utimensat(2) und ahnliche). (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 hinzugefugt werden. Um Benachrichtigungen fur alle Ereignisse zu deaktivieren, fuhren Sie einen Aufruf F_NOTIFY mit arg als 0 durch. Benachrichtigungen erfolgen uber die Zustellung eines Signals. Das Standardsignal ist SIGIO, dies kann aber mittels des Befehls F_SETSIG von fcntl() geandert werden. (Beachten Sie, dass SIGIO eines der nichtwarteschlangenfahigen Standardsignale ist; wird auf Echtzeitsignale umgestellt, konnen mehrere Benachrichtigungen fur den Prozess in die Warteschlange gestellt werden). Im letzteren Falle erhalt 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 enthalt einen Dateideskriptor, der die Benachrichtigung erstellte (nutzlich, falls Benachrichtigungen fur mehrere Verzeichnisse eingerichtet werden). Insbesondere bei der Verwendung von DN_MULTISHOT sollte ein Echtzeitsignal fur die Benachrichtigung verwandt werden, so dass mehrere Benachrichtigungen in die Warteschlange aufgenommen werden konnen. HINWEIS: Neue Anwendungen sollten die Schnittstelle inotify (verfugbar seit Linux 2.6.13) verwenden, die eine deutlich uberlegene Schnittstelle zur Ermittlung von Benachrichtigungen uber Dateisystemereignisse bietet. Siehe inotify(7). Andern der Kapazitat einer Pipe F_SETPIPE_SZ (int; seit Linux 2.6.35) Andert die Kapazitat der durch dd referenzierten Pipe auf mindestens arg Byte. Ein unprivilegierter Prozess kann die Pipe-Kapazitat auf jeden Wert zwischen der Systemseitengrosse und der durch /proc/sys/fs/pipe-max-size (siehe proc(5)) definierten Grenze anpassen. Wird versucht, die Pipe-Kapazitat unter die Seitengrosse zu setzen, dann wird diese ohne Ruckmeldung auf die Seitengrosse gerundet. Versucht ein unprivilegierter Prozess, die Pipe-Kapazitat uber die in /proc/sys/fs/pipe-max-size definierte Grenze zu setzen, fuhrt dies zu dem Fehler EPERM; ein privilegierter Prozess (CAP_SYS_RESOURCE) kann die Grenze ausser Kraft setzen. Beim Reservieren des Puffers fur die Pipe darf der Kernel eine grossere Kapazitat als arg verwenden, falls das fur die Implementierung passend ist. (In der aktuellen Implementierung ist die Allokation die nachst-grossere Zweierpotenz des Vielfachen der Seitengrosse der angeforderten Grosse.) Die tatsachliche gesetzte Kapazitat (in Byte) wird als Ergebnis der Funktion zuruckgeliefert. Wird versucht, die Pipe-Kapazitat 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 Grosse sein kann, abhangig von der Grosse der Schreibvorgange. F_GETPIPE_SZ (void; seit Linux 2.6.35) Liefert (als Ergebnis der Funktion) die Kapazitat der durch dd referenzierten Pipe zuruck. Versiegelung von Dateien Dateisiegel begrenzen die Menge der erlaubten Aktionen fur eine bestimmte Datei. Fur 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 hangt von der Art der unterliegenden Datei und dem Dateisystem ab. Fur einen Uberblick uber Dateiversiegelung, einer Diskussion ihres Zwecks und Code-Beispiele siehe memfd_create(2). Derzeit konnen Dateisiegel nur auf durch memfd_create(2) zuruckgelieferte Dateideskriptoren angewandt werden (falls MFD_ALLOW_SEALING eingesetzt wurde). Auf anderen Dateisystemen werden alle fcntl()-Aktionen zur Versiegelung EINVAL zuruckliefern. Siegel sind eine Eigenschaft eines Inodes. Daher verfugen alle offenen Dateideskriptoren, die auf den gleichen Inode verweisen, uber die gleiche Gruppe an Siegeln. Desweiteren konnen Siegel nie entfernt, nur hinzugefugt werden. F_ADD_SEALS (int; seit Linux 3.17) Fugt die im Bitmasken-Argument arg ubergebenen Siegel zu der Gruppe der Siegel des Inodes, der vom Dateideskriptor dd referenziert wird, hinzu. Siegel konnen nicht mehr entfernt werden. Sobald dieser Aufruf gelingt, werden die Siegel sofort vom Kernel durchgesetzt. Falls die derzeitige Gruppe der Siegel F_SEAL_SEAL enthalt (siehe unten) wird dieser Aufruf mit EPERM abgelehnt. Hinzufugen 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 zuruck. Falls keine Siegel gesetzt sind, wird 0 zuruckgeliefert. Falls die Datei Versiegelung nicht unterstutzt, wird -1 zuruckgeliefert und errno auf EINVAL gesetzt. Die folgenden Versiegelungen sind verfugbar: F_SEAL_SEAL Falls dieses Siegel gesetzt ist, wird jeder zukunftige Aufruf von fcntl() mit F_ADD_SEALS mit dem Fehler EPERM fehlschlagen. Daher verhindert dieses Siegel jede Anderung an der Siegelmenge selbst. Falls die ursprungliche Siegelmenge einer Datei F_SEAL_SEAL enthalt, dann fuhrt 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. Vergrossern der Datei ist weiterhin moglich. F_SEAL_GROW Falls dieses Siegel gesetzt ist, kann die in Frage kommende Datei nicht vergrossert werden. Dies betrifft write(2) uber das Ende der Datei hinaus, truncate(2), ftruncate(2) und fallocate(2). Diese Aufrufe schlagen mit EPERM fehl, falls Sie versuchen, diese zum Vergrossern der Datei zu verwenden. Falls Sie die Dateigrosse beibehalten oder verkleinern, werden diese Aufrufe weiterhin wie erwartet funktionieren. F_SEAL_WRITE Falls dieses Siegel gesetzt ist, konnen Sie den Inhalt der Datei nicht verandern. Beachten Sie, dass das Verkleinern oder Vergrossern der Grosse der Datei weiterhin moglich 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 mussen vor dem Hinzufugen dieses Siegels aufgehoben werden. Weiterhin werden alle ausstehenden Schreibvorgange 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 ahnlich zu F_SEAL_WRITE, aber der Inhalt der Datei kann weiterhin mittels gemeinsamen schreibbaren Mappings, die vor dem Setzen des Siegels erstellt wurden, verandert 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 verandern kann und der gleichzeitig von anderen Prozessen >>nur lesend<< mitgenutzt werden kann. Datei Lese-/Schreibehinweise Der Kernel kann mit Schreib-Lebenszeithinweisen uber die erwartete relative Lebenszeit von Schreibaktionen an einer benannten Inode oder uber eine bestimmte offene Dateideskription informiert werden (Siehe open(2) fur eine Erlauterung von offenen Dateideskriptoren.). In diesem Kontext bedeutet der Ausdruck >>Schreib-Lebenszeit<<, die erwartete Zeit, die die Daten auf dem Medium verbleiben, bevor sie uberschrieben oder geloscht 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 konnen. Allerdings implizieren diese Schalter keine funktionalen Semantiken und verschiedene E/A-Klassen konnen die Schreib-Lebenszeithinweise in beliebigen Arten benutzen, so lange die Hinweise konsistent benutzt werden. Die folgenden Aktionen konnen 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 geandert oder das unterliegende Dateisystem ausgehangt 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 gultig: 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 uber diesen offenen Dateideskriptor geschrieben werden, eine kurze Lebenszeit haben werden. RWH_WRITE_LIFE_MEDIUM Es wird erwartet, dass Daten, die in diese Inode oder uber diesen offenen Dateideskriptor geschrieben werden, eine langere 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 uber diesen offenen Dateideskriptor geschrieben werden, eine langere 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 uber diesen offenen Dateideskriptor geschrieben werden, eine langere 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. RUCKGABEWERT Fur einen erfolgreichen Aufruf hangt der Ruckgabewert 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-Eigentumers. F_GETSIG Wert des Signals, wenn Lesen oder Schreiben moglich wird, oder Null fur traditionelles SIGIO-Verhalten. F_GETPIPE_SZ F_SETPIPE_SZ Die Kapazitat der Pipe. F_GET_SEALS Eine Bitmaske, die die Siegel identifiziert, die fur den durch dd referenzierten Inode gesetzt wurden. Alle anderen Befehle Null Bei einem Fehler wird -1 zuruckgegeben 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 Offnungsmodus des Dateideskriptors passt nicht auf die angeforderte Art der Sperre. EBUSY Bef ist F_SETPIPE_SZ und die in arg angegebene neue Kapazitat der Pipe ist kleiner als die Grosse des derzeit zur Speicherung von Daten in der Pipe verwandten Pufferspeichers. EBUSY Bef ist F_ADD_SEALS, arg enthalt 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 fuhren wurde. EFAULT lock befindet sich ausserhalb 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 gepruft oder erworben werden konnte. Passiert am wahrscheinlichsten beim Sperren von Dateien in der Ferne (d.h. Sperren uber 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 enthalt ein nicht erkanntes Versiegelungs-Bit. EINVAL Bef ist F_ADD_SEALS oder F_GET_SEALS und das Dateisystem, das den durch dd referenzierten Inode enthalt, unterstutzt kein Versiegeln. EINVAL Bef ist F_DUPFD und arg ist negativ oder ist grosser als der maximal zulassige 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 Beschrankung pro Prozess fur 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 uber 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-Beschrankung wurde erreicht; siehe pipe(7). EPERM Es wurde versucht, den Schalter O_APPEND auf einer Datei zuruckzusetzen, bei der das Attribut >>nur anhangen<< gesetzt ist. EPERM Bef war F_ADD_SEALS aber dd war nicht zum Schreiben offen oder die aktuelle Menge der Siegel der Datei enthalt bereits F_SEAL_SEAL. STANDARDS POSIX.1-2008. 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 nachsten Version von POSIX.1 enthalten sind. F_ADD_SEALS und F_GET_SEALS sind Linux-spezifisch. GESCHICHTE 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 grosser oder gleich 500 oder definieren Sie _POSIX_C_SOURCE mit einem Wert grosser 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 grosser oder gleich 200809L oder _XOPEN_SOURCE mit einem Wert grosser oder gleich 700.) ANMERKUNGEN Die Fehler, die von dup2(2) zuruckgegeben werden, sind anders als die von F_DUPFD. Sperrung von Dateien Der ursprungliche Systemaufruf fcntl() von Linux war nicht dafur konstruiert, grosse Dateiversatze (in der Struktur flock) zu handhaben. Konsequenterweise wurde ein Systemaufruf fcntl64() in Linux 2.4 hinzugefugt. 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 konnen allerdings von Anwendungen, die Glibc einsetzen, ignoriert werden, da dessen Wrapperfunktion fcntl() transparent den neueren Systemaufruf einsetzt, wo er verfugbar 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 nutzlich ist, falls der Prozess, der die Sperre halt, auf einer anderen Maschine existiert. Unter Linux wird dieses Feld, auch wenn es auf einigen Architekturen (wie MIPS32) vorhanden ist, nicht verwandt. Der ursprungliche Systemaufruf fcntl() von Linux war nicht dafur konstruiert, grosse Dateiversatze (in der Struktur flock) zu handhaben. Konsequenterweise wurde ein Systemaufruf fcntl64() in Linux 2.4 hinzugefugt. 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 konnen allerdings von Anwendungen, die Glibc einsetzen, ignoriert werden, da dessen Wrapperfunktion fcntl() transparent den neueren Systemaufruf einsetzt, wo er verfugbar ist. Datensatzsperren und NFS Falls ein NFSv4-Client vor Linux 3.12 den Kontakt mit dem Server fur 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 ausdruckt, bestimmt werden. Der Vorgabewert fur diese Datei ist 90.) In diesem Szenario sind potenziell Datenbeschadigungen moglich, da ein anderer Prozess in der Zwischenzeit eine Sperre erlangen und Datei-E/A durchfuhren konnte. 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 schliesst und erneut offnet. 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 Datenverfalschung ist die Vorgabe fur diesen Parameter 0 (deaktiviert). FEHLER F_SETFL Es ist nicht moglich, F_SETFL zum Andern des Zustands der Schalter O_DSYNC und O_SYNC zu verwenden. Versuche, den Zustand dieser Schalter zu andern, werden ohne Meldung ignoriert. F_GETOWN Eine Begrenzung der Linux-Systemaufrufkonventionen auf einigen Architekturen (insbesondere i386) bedeutet, dass, falls eine von F_GETOWN zuruckgelieferte (negative) Prozessgruppenkennung in den Bereich -1 bis -4095 fallt, dies von Glibc falschlicherweise als Fehler im Systemaufruf interpretiert wird. Dann wird der Ruckgabewert 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 alter gibt es einen Fehler, der auftreten kann, wenn ein unprivilegierter Prozess statt einem Aufrufenden F_SETOWN verwendet, um den Eigentumer eines Socket-Dateideskriptors als Prozess(gruppe) festzulegen. In diesem Fall kann fcntl() -1 mit errno auf EPERM gesetzt zuruckliefern, selbst wenn der/die Eigentumerprozess(gruppe) dergestalt ist, dass der Aufrufende Rechte hat, ihr/ihm Signale zu senden. Trotz dieses zuruckgelieferten Fehlers wird der Dateieigentumer gesetzt und Signale werden zum Eigentumer 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 Abhangigkeitssuche auf 10 Schritte, was bedeutet, dass zirkulare Verklemmungsketten, die diese Grosse uberschreiten, nicht erkannt werden. Zusatzlich kann der Kernel falschlicherweise 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 Ressourcenwettlaufen, die sie unzuverlassig machen: Ein write(2)-Aufruf, der sich mit einer Sperre uberschneidet, kann Daten verandern, nachdem die Pflichtsperre erlangt wurde. Ein read(2)-Aufruf, der sich mit einer Sperre uberschneidet, kann Anderungen an Daten entdecken, die nur vorgenommen wurden, nachdem eine Schreibsperre erlangt wurde. Ahnliche Wettlaufe 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 alteren Kerneln befinden sich diese Dateien direkt unter dem Verzeichnis Documentation/ und mandatory-locking.txt heisst mandatory.txt.) UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Martin Schulze , Chris Leick , Helge Kreutzmann und Mario Blattermann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . Linux man-pages 6.06 31. Oktober 2023 fcntl(2)