Provided by: manpages-pl-dev_4.27.0-1_all 

NAZWA
fcntl - manipuluje deskryptorem pliku
BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)
SKŁADNIA
#include <fcntl.h>
int fcntl(int fd, int op, ... /* arg */ );
OPIS
fcntl dokonuje jednej z operacji opisanych poniżej na otwartym deskryptorze pliku fd. Wykonywana operacja
jest określona przez op.
fcntl() opcjonalnie może przyjąć trzeci argument. To, czy argument ten jest wymagany, zależy od op.
Wymagany typ argumentu jest wskazany w nawiasie po każdej nazwie op (zwykle wymaganym typem jest int, a
argument jest identyfikowany określeniem arg) lub podane jest void, gdy argument nie jest wymagany.
Niektóre z poniższych operacji są obsługiwane jedynie w określonej wersji jądra Linux. Preferowaną metodą
sprawdzenia, czy działające aktualnie jądro obsługuje daną operację, jest przywołanie fcntl() z daną
wartością op i sprawdzenie, czy wywołanie zawiedzie z błędem EINVAL wskazując, że jądro nie rozpoznało
tej wartości.
Duplikowanie deskryptora pliku
F_DUPFD (int)
Duplikuje deskryptor pliku fd za pomocą najniższego dostępnego numeru deskryptora pliku większego
lub równego arg. Różni się to od dup2(2), korzystającego z konkretnego, zadanego deskryptora.
Po pomyślnym zakończeniu zwracany jest nowy deskryptor pliku.
Więcej informacji znajduje się w podręczniku dup(2).
F_DUPFD_CLOEXEC (int; od Linuksa 2.6.24)
Jak w przypadku F_DUPFD, lecz dodatkowo ustawia znacznik zamknięcia-przy-wykonaniu dla
duplikowanego deskryptora pliku. Podanie tego znacznika umożliwia programowi na uniknięcie
dodatkowej operacji F_SETFD fcntl(), w celu ustawienia znacznika FD_CLOEXEC. Wyjaśnienie powodu,
dla którego znacznik ten jest przydatny, znajduje się w opisie O_CLOEXEC w podręczniku open(2).
Znaczniki deskryptora pliku
Następujące operacje kontrolują znaczniki powiązane z deskryptorem pliku. Obecnie zdefiniowano jedynie
jeden taki znacznik: FD_CLOEXEC, znacznik zamknięcia-przy-wykonaniu. Jeśli ustawiony jest bit FD_CLOEXEC,
to deskryptor pliku zostanie automatycznie zamknięty podczas pomyślnego wykonania execve(2) (jeśli
execve(2) zawiedzie, deskryptor pliku jest pozostawiany otwarty). Jeśli bit FD_CLOEXEC nie jest
ustawiony, deskryptor pliku pozostanie otwarty podczas wykonania execve(2).
F_GETFD (void)
Zwraca (jako wynik funkcji) znaczniki deskryptora pliku; argument arg jest ignorowany.
F_SETFD (int)
Ustawia znaczniki deskryptora pliku na wartość określoną w arg.
W programach wielowątkowych, użycie F_SETFD fcntl() do ustawienia znacznika zamknięcia przy uruchomieniu
w tym samym czasie, w którym inny wątek wykonuje fork(2) i execve(2) jest narażone na wystąpienie
sytuacji wyścigu, która może niezamierzenie prowadzić do wycieku deskryptora pliku do programu
wykonującego proces potomny. Szczegóły i sposób na uniknięcie tego problemu opisano przy znaczniku
O_CLOEXEC, w podręczniku open(2).
Znaczniki stanu pliku
Z każdym opisem otwartego pliku stowarzyszonych jest kilka znaczników inicjowanych przez open(2), które
mogą ewentualnie być modyfikowane przez fcntl(2). Zduplikowane deskryptory pliku (utworzone za pomocą
dup(2), fork(2), itp.) odnoszą się do tego samego opisu otwartego pliku, dzieląc zatem te same znaczniki
stanu pliku.
Znaczniki stanu pliku i ich znaczenie są opisane w open(2).
F_GETFL (void)
Zwraca (jako wynik funkcji) tryb dostępu do pliku i znaczniki stanu pliku, arg jest ignorowany.
F_SETFL (int)
Ustawia znaczniki stanu pliku na wartości określone przez arg. W arg ignorowane są: tryb dostępu
do pliku (O_RDONLY, O_WRONLY, O_RDWR) oraz znaczniki tworzenia pliku (tj. O_CREAT, O_EXCL,
O_NOCTTY, O_TRUNC). W Linuksie, operacja ta może zmienić jedynie znaczniki O_APPEND, O_ASYNC,
O_DIRECT, O_NOATIME i O_NONBLOCK. Nie da się zmienić znaczników O_DSYNC i O_SYNC; zob. USTERKI
niżej.
Blokowanie doradcze rekordów
Linux implementuje tradycyjne („powiązane z procesem”) blokady rekordów UNIX, zgodnie ze standardem
POSIX. Istnieje również typowo linuksowa alternatywa używająca lepszej semantyki — blokady opisów
otwartego pliku, które są opisane nieco niżej.
F_SETLK, F_SETLKW i F_GETLK służą do zakładania, zwalniania i sprawdzania obecności blokad rekordów
(znanych również jako blokady zakresu bajtów, segmentów pliku lub obszarów pliku). Trzeci argument, lock,
jest wskaźnikiem do struktury zawierającej co najmniej następujące pola (kolejność nie jest określona).
struct flock {
...
short l_type; /* Rodzaj blokady: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* Sposób interpretacji l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Początek (przesunięcie) blokady */
off_t l_len; /* Liczba blokowanych bajtów */
pid_t l_pid; /* PID procesu uniemożliwiającego blokadę
(ustawiane przez F_GETLK i F_OFD_GETLK) */
...
};
Pola l_whence, l_start i l_len w tej strukturze określają zakres bajtów, które mają ulec zablokowaniu.
Bajty po końcu pliku mogą być blokowane, nie mogą to być natomiast bajty przed jego początkiem.
l_start jest początkowym przesunięciem blokady i jest interpretowane w odniesieniu do: początku pliku
(gdy l_whence wynosi SEEK_SET), bieżącego przesunięcia pliku (gdy l_whence wynosi SEEK_CUR) albo końca
pliku (gdy l_whence wynosi SEEK_END). W ostatnich dwóch przypadkach, l_start może być liczbą ujemną
zakładając, że przesunięcie nie prowadzi przed początek pliku.
l_len określa liczbę bajtów do zablokowania. Jeśli l_len jest dodatnie, to przedział do zablokowania
pokrywa bajty od l_start do l_start+l_len-1 włącznie. Podanie 0 w l_len ma specjalne znaczenie: blokowane
są wszystkie bajty od położenia określonego przez l_whence i l_start, aż do końca pliku, niezależnie od
tego, jak duży staje się plik.
POSIX.1-2001 zezwala implementacji (lecz tego nie wymaga) na obsługę ujemnych wartości l_len; jeśli l_len
jest ujemna, to przedział, którego dotyczy lock obejmuje bajty od l_start+l_len do l_start-1 włącznie.
Jest to obsługiwane od Linuksa 2.4.21 i Linuksa 2.5.49.
Pole l_type może służyć do założenia blokady dla odczytu (F_RDLCK) lub dla zapisu (F_WRLCK) do pliku.
Dowolna liczba procesów może utrzymywać blokadę dla odczytu pliku (blokada wspólna) w pewnym jego
obszarze, ale tylko jeden proces może utrzymywać blokadę dla zapisu do pliku (blokada wyłączna). Blokada
wyłączna wyklucza wszelkie inne blokady, zarówno wspólne, jak i wyłączne. Pojedynczy proces może w danym
obszarze pliku utrzymywać blokadę tylko jednego rodzaju; gdy w aktualnie zablokowanym obszarze zakładana
jest nowa blokada, to istniejąca blokada jest przekształcana w blokadę nowego typu (takie przekształcenie
może pociągać za sobą podział, skrócenie lub połączenie z istniejącą blokadą, gdy zakres bajtów podany
dla nowej blokady nie pokrywa się dokładnie z zakresem istniejącej blokady).
F_SETLK (struct flock *)
Ustawienie blokady dla zakresu bajtów określonego przez pola l_whence, l_start i l_len lock (gdy
l_type jest równe F_RDLCK lub F_WRLCK) albo jej zwolnienie (gdy l_type jest równe F_UNLCK). Jeśli
kolidująca blokada jest utrzymywana przez inny proces, funkcja ta zwraca -1 i ustawia errno na
EACCES lub EAGAIN (zwracany w tym przypadku błąd różni się pomiędzy implementacjami, dlatego POSIX
wymaga sprawdzania przez przenośne aplikacje obu wartości błędów).
F_SETLKW (struct flock *)
Podobne do F_SETLK, lecz w sytuacji, gdy na pliku założona jest kolidująca blokada czeka na
zwolnienie tej blokady. Jeśli podczas oczekiwania zostanie przechwycony sygnał, funkcja jest
przerywana i (po powrocie z funkcji obsługi sygnału) powraca natychmiast (zwracając wartość -1 i
ustawiając errno na EINTR; zob. signal(7)).
F_GETLK (struct flock *)
Jako argument lock tej funkcji określa blokadę, jaką chcielibyśmy założyć na pliku. Gdy założenie
blokady jest możliwe, fcntl() w rzeczywistości jej nie zakłada, lecz zwraca F_UNLCK w polu l_type
struktury lock pozostawiając inne pola tej struktury niezmienione.
Jeśli jedna lub więcej niezgodnych blokad zapobiegłoby umieszczeniu tej blokady, to fcntl() zwróci
szczegóły o jednej z tych blokad w polach l_type, l_whence, l_start i l_len w lock. Jeśli
niezgodna blokada jest tradycyjną (związaną z procesem) blokadą rekordu, to pole l_pid jest
ustawiane na PID procesu utrzymującego tę blokadę. Jeśli niezgodna blokada jest blokadą opisu
otwartego pliku (OFD), to l_pid jest ustawiane na -1. Proszę zauważyć, że w momencie sprawdzenia
zwracanych informacji przez wywołującego, mogą być już one nieaktualne.
Aby założyć blokadę do odczytu, deskryptor fd musi być otwarty do odczytu. Aby założyć blokadę do zapisu,
deskryptor fd musi być otwarty do zapisu. Aby założyć obydwa rodzaje blokad, należy otworzyć plik do
odczytu i zapisu.
Przy umieszczaniu blokady z F_SETLKW, jądra wykrywa zakleszczenia, gdy żądania blokad dwóch lub więcej
procesów są wzajemnie zablokowane przez blokady utrzymywane przez inne procesy. Przykładowo, przypuśćmy,
że proces A utrzymuje blokadę zapisu na bajcie 100. pliku, a proces B utrzymuje blokadę zapisu na bajcie
200. Jeśli każdy z procesów spróbuje następnie zablokować bajt już zablokowany przez drugie proces za
pomocą F_SETLKW, to — bez wykrywania zakleszczeń — oba procesy pozostałyby stale zablokowane. Jeśli jądro
wykryje takie zakleszczenie, to spowoduje natychmiastowe niepowodzenie jednego z żądań blokady, z błędem
EDEADLK; aplikacja napotykająca na taki błąd powinna zwolnić niektóre ze swoich blokad, aby pozwolić
działać inny aplikacjom, przed ponowną próbą odzyskania wymaganych blokad. Wykrywane są również koliste
zakleszczenia, z więcej niż dwoma procesami. Proszę jednak zauważyć, że algorytm wykrywania zakleszczeń
jądra ma swoje ograniczenia, zob. USTERKI.
Oprócz usunięcia za pomocą wyraźnego F_UNLCK, blokady rekordów są zwalniane automatycznie po zakończeniu
procesu.
Blokady rekordów nie są dziedziczone przez procesy potomne poprzez fork(2), ale są zachowywane poprzez
execve(2).
Ze względu na wykonywane przez bibliotekę stdio(3) buforowanie, należy unikać blokowania rekordów w
połączeniu z funkcjami z tego pakietu; zamiast tego należy używać read(2) i write(2).
Opisane wyżej blokady rekordów są związane z procesem (w przeciwieństwie do blokad opisu otwartego pliku,
opisanych niżej). Ma to pewne niefortunne konsekwencje:
• Jeśli proces zamknie dowolny deskryptor odnoszący się do pliku, to zwalniane są wszystkie blokady,
niezależnie od tego, na którym z deskryptorów pliku blokady te uzyskano. Jest to złe: oznacza, że
proces może utracić swe blokady na pliku takim jak /etc/passwd lub /etc/mtab gdy jakaś funkcja
biblioteczna zdecyduje się z jakiegoś powodu otworzyć, odczytać i zamknąć ten sam plik.
• Wątki procesu dzielą blokady. Innymi słowy, program wielowątkowy nie może korzystać z blokad rekordów,
aby uniemożliwić jednoczesny dostęp do tego samego miejsca pliku przez swoje wątki.
Blokady opisu otwartego pliku rozwiązują oba te problemy.
Blokady opisu otwartego pliku (spoza POSIX)
Blokady opisu otwartego pliku są blokadami doradczymi, definiowanymi w zakresie bajtów, których działanie
jest w większości identyczne do tradycyjnych blokad rekordów opisanych wyżej. Ten typ blokad jest typowo
linuksowy i jest dostępny od Linuksa 3.15 (w Austin Group istnieje propozycja włączenia tego typu blokady
do następnej rewizji POSIX.1). Wyjaśnienie opisu otwartego pliku znajduje się w podręczniku open(2).
Podstawową różnicą, pomiędzy dwoma typami blokad jest fakt, że o ile tradycyjne blokady rekordów są
związane z procesem, to blokady opisu otwartego pliku są związane z opisem otwartego pliku, na którym je
uzyskano, podobnie jak to wygląda w przypadku blokad uzyskanych za pomocą flock(2). W efekcie (inaczej
niż przy tradycyjnych blokadach doradczych rekordów) blokady opisu otwartego pliku są dziedziczone przy
fork(2) (i clone(2) ze znacznikiem CLONE_FILES), a także są automatycznie zwalniane po ostatnim
zamknięciu opisu otwartego pliku, zamiast zwalniania przy jakimkolwiek zamknięciu pliku.
Kolidujące kombinacje blokad (tj. blokada odczytu z blokadą zapisu lub dwie blokady zapisu) gdy jedna
blokada jest blokadą opisu otwartego pliku, a druga jest tradycyjną blokadą rekordu prowadzą do konfliktu
nawet wówczas, gdy są uzyskane przez ten sam proces na tym samym deskryptorze pliku.
Blokady opisu otwartego pliku umieszczone na tym samym opisie otwartego pliku (tj. za pomocą tego samego
deskryptora pliku lub za pomocą duplikatu deskryptora pliku utworzonego przez fork(2), dup(2), F_DUPFD z
fcntl() itp.) są zawsze kompatybilne: jeśli nowa blokada jest umieszczona na już zablokowanym rejonie
pliku, to istniejące blokada jest konwertowana na nowy typ blokady (takie konwersje mogą prowadzić to
podziału, zmniejszenia lub złączenia z dotychczasową blokadą, jak opisano to wyżej)
Z drugiej strony, blokady opisu otwartego pliku mogą być w konflikcie, gdy są uzyskane przez różne opisy
otwartego pliku. Z tego względu, program wielowątkowy może korzystać z blokad opisu otwartego pliku do
synchronizowania dostępu do jakiegoś miejsca w pliku, otwierając (open(2)) plik z różnych wątków i
zakładając blokady za pomocą wynikowego deskryptora pliku.
Podobnie jak w przypadku tradycyjnych blokad doradczych, trzeci argument do fcntl() — lock, jest
wskaźnikiem do struktury flock. W odróżnieniu do tradycyjnych blokad rekordów, pole l_pid tej struktury
musi być ustawione na zero za pomocą operacji opisanych niżej.
Operacje działające z blokadami opisu otwartego pliku są analogiczne do tych używanych z tradycyjnymi
blokadami:
F_OFD_SETLK (struct flock *)
Ustawia blokadę opisu otwartego pliku (gdy l_type jest równe F_RDLCK lub F_WRLCK) albo zwalnia
blokadę opisu otwartego pliku (gdy l_type jest równe F_UNLCK) dla zakresu bajtów określonego przez
pola l_whence, l_start i l_len lock. Jeśli kolidująca blokada jest utrzymywana przez inny proces,
funkcja ta zwraca -1 i ustawia errno na EAGAIN.
F_OFD_SETLKW (struct flock *)
Podobne do F_SETLK, lecz w sytuacji, gdy na pliku założona jest kolidująca blokada, czeka na
zwolnienie tej blokady. Jeśli podczas oczekiwania zostanie przechwycony sygnał, funkcja jest
przerywana i (po powrocie z funkcji obsługi sygnału) powraca natychmiast (zwracając wartość -1 i
ustawiając errno na EINTR; zob. signal(7)).
F_OFD_GETLK (struct flock *)
Jako argument lock tej funkcji określa blokadę opisu otwartego pliku, jaką chcielibyśmy założyć na
pliku. Gdy założenie blokady jest możliwe, fcntl() w rzeczywistości jej nie zakłada, lecz zwraca
F_UNLCK w polu l_type struktury lock pozostawiając inne pola tej struktury niezmienione. Jeśli co
najmniej jedna niezgodna blokada uniemożliwiłaby założenie zadanej blokady, to informacje o jednej
z tych blokad są zwracane za pomocą lock, jak to opisano powyżej dla F_GETLK.
W bieżącej implementacji, dla blokad opisu otwartego pliku nie zachodzi wykrywanie zakleszczeń (w
odróżnieniu od blokad rekordów związanych z procesem, dla których jądro wykonuje wykrywanie zakleszczeń).
Blokowanie obowiązujące (przymusowe)
Ostrzeżenie: linuksowa implementacja blokowania obowiązującego jest zawodna (zob. USTERKI poniżej). Z
powodu opisanych błędów i faktu, że funkcjonalność ta nie była często wykorzystywana, od Linuksa 4.5,
tego typu blokowanie stało się opcjonalne i zależy od ustawienia opcji konfiguracyjnej
(CONFIG_MANDATORY_FILE_LOCKING). Od Linuksa 5.15 blokowanie obowiązujące (przymusowe) nie jest już w
ogólne obsługiwane.
Domyślnie, zarówno tradycyjne blokady (związane z procesem) jak i blokady opisu otwartego pliku (OFD) są
doradcze. Blokady doradcze nie są wymuszane i są przydatne tylko w przypadku współdziałających procesów.
Oba te typy mogą być również obowiązujące. Blokady obowiązujące są wymuszane dla wszystkich procesów.
Jeśli proces spróbuje uzyskać niezgodny dostęp (tj. odczyt — read(2) lub zapis — write(2)) w obszarze
pliku, który posiada niezgodną blokadę obowiązującą, to wynik zależy od tego, czy dla jego opisu
otwartego pliku włączono znacznik O_NONBLOCK. Jeśli znacznik O_NONBLOCK nie jest włączony, to dane
wywołanie systemowe jest blokowane do momentu usunięcia blokady lub jej przekształcenia w tryb, który
jest zgodny z uzyskiwanym dostępem. Jeśli znacznik O_NONBLOCK jest włączony, to wywołanie systemowe
zawodzi z błędem EAGAIN.
Aby skorzystać z obowiązujących blokad, blokowanie obowiązujące musi być włączone zarówno na systemie
plików zawierającym blokowany plik, jak i na samym pliku. Blokowanie obowiązujące w systemie plików
włącza się za pomocą opcji „-o mand” programu mount(8) lub za pomocą znacznika MS_MANDLOCK do mount(8).
Blokowanie obowiązujące na pliku włącza się poprzez wyłączenie prawa uruchamiania dla grupy i włączenie
bitu set-group-ID (zob. chmod(1) i chmod(2)).
Blokowanie obowiązujące nie jest określone normą POSIX. Niektóre inne systemy również obsługują
blokowanie obowiązujące, choć szczegóły ich włączenia również się między systemami.
Zagubione blokady
Gdy blokada doradcza jest uzyskiwana na sieciowym systemie plików, takim jak NFS, możliwe jest zagubienie
blokady. Może się tak stać ze względu na działanie administracyjne na serwerze lub z powodu podziału
sieci (tzn. utraty połączenie z serwerem), które będzie trwało na tyle długo, że serwer może przyjąć brak
dalszego funkcjonowania przez klienta.
Gdy system plików stwierdzi, że blokada została zagubiona, przyszły odczyt (read(2)) lub zapis (write(2))
może zawieść z błędem EIO. Błąd ten będzie występował do momentu usunięcia blokady lub zamknięcia
deskryptora pliku. Od Linuksa 3.12, dzieje się tak przynajmniej w NFSv4 (we wszystkich jego pomniejszych
wydaniach).
Niektóre wersje Uniksa wysyłają w takiej sytuacji sygnał (SIGLOST). Linux nie definiuje tego sygnału i
nie zapewnia żadnego asynchronicznego powiadamiania o zagubionych blokadach.
Zarządzanie sygnałami
F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG i F_SETSIG służą do zarządzania sygnałami
dostępności wejścia/wyjścia:
F_GETOWN (void)
Zwraca (jako wynik funkcji) identyfikator procesu lub identyfikator grupy procesów aktualnie
otrzymujących sygnały SIGIO i SIGURG dla zdarzeń na deskryptorze plików fd. Identyfikatory
procesów są zwracane jako wartości dodatnie, identyfikatory grupy procesów są zwracane jako
wartości ujemne (lecz zob. USTERKI poniżej). arg jest ignorowane.
F_SETOWN (int)
Ustawia identyfikator procesu lub identyfikator grupy procesów aktualnie otrzymujących sygnały
SIGIO i SIGURG dla zdarzeń na deskryptorze plików fd. Docelowy identyfikator procesu lub grupy
procesów podaje się jako arg. Identyfikator procesu jest określany jako liczba dodatnia;
identyfikator grupy procesów jest określany za pomocą wartości ujemnych. Najczęściej, proces
wywołujący określa się jako właściciel (tj. arg jest podawany jak przez getpid(2)).
Oprócz ustawiania właściciela deskryptora pliku, konieczne jest również włączenie generowania
sygnałów na deskryptorze plików. Można to uczynić za pomocą operacji F_SETFL fcntl(), ustawiając
znacznik stanu pliku O_ASYNC na deskryptorze pliku. Co za tym idzie, gdy tylko na deskryptorze
pliku możliwe stanie się wejście lub wyjście, zostanie wysłany sygnał SIGIO. Operację F_SETSIG
fcntl() można wykorzystać do uzyskania dostarczenia sygnału innego niż SIGIO.
Wysłanie sygnału do właściciela procesu (grupy) podanego w F_SETOWN, podlega takim samym
sprawdzeniom uprawnień jak opisano w przypadku kill(2), gdy proces wysyłający jest tym, który
używa F_SETOWN (lecz zob. USTERKI poniżej). Jeśli sprawdzenie uprawnień się nie powiedzie, to
sygnał jest po cichu odrzucany. Uwaga: Operacja F_SETOWN sprawdza poświadczenia wywołującego w
chwili wywołania fcntl() i to te zapisane poświadczenia są używane do sprawdzenia uprawnień.
Jeśli deskryptor pliku fd odnosi się do gniazda, F_SETOWN określa również odbiorcę sygnałów SIGURG
dostarczanych gdy poprzez gniazdo przybędą dane autonomiczne (SIGURG jest wysyłany w sytuacjach, w
których select(2) zgłosiłby „stan wyjątkowy”).
Następujący akapit był prawdziwy w Linuksie 2.6.x do Linuksa 2.6.11 włącznie:
Jeśli F_SETSIG przekaże się wartość niezerową w procesie wielowątkowym, działającym z
biblioteką wątkowania obsługującą grupy wątków (np. NPTL), to wartość pozytywna przekazana
F_SETOWN ma inne znaczenie: zamiast byciem identyfikatorem całego procesu, jest
identyfikatorem wątku, który identyfikuje dany wątek procesu. W efekcie, może być konieczne
podanie F_SETOWN wyniku gettid(2), zamiast wyniku getpid(2), aby uzyskać rozsądne wyniki,
gdy korzysta się z F_SETSIG (w bieżącej, linuksowej implementacji wątkowania, identyfikator
głównego wątku jest taki sam jak jego identyfikator procesu; oznacza to, że programy
jednowątkowe mogą w tym scenariuszu korzystać z gettid(2) lub getpid(2)). Proszę jednak
zauważyć, że stwierdzenie w tym akapicie nie dotyczy sygnału SIGURG, wygenerowanego dla
danych spoza pasma (ang. out-of-band data) na gnieździe: ten sygnał zawsze trafia albo do
procesu albo do grupy procesu, w zależności od wartości przekazanej F_SETOWN.
Powyższe zachowanie przypadkowo porzucono w Linuksie 2.6.12 i nie zostanie przywrócone. Od Linuksa
2.6.32, należy użyć F_SETOWN_EX, aby przeznaczyć sygnały SIGIO do określonego wątku.
F_GETOWN_EX (struct f_owner_ex *) (od Linuksa 2.6.32)
Zwraca ustawienia aktualnego właściciela deskryptora pliku, jak zdefiniowane poprzednią operacją
F_SETOWN_EX. Informacja ta jest zwracana przez strukturę na którą wskazuje arg, która ma postać:
struct f_owner_ex {
int type;
pid_t pid;
};
Pole type będzie miało jedną z wartości: F_OWNER_TID, F_OWNER_PID lub F_OWNER_PGRP. Pole pid jest
liczbą dodatnią, reprezentującą identyfikator, odpowiednio, wątku, procesu lub grupy procesu.
Więcej informacji przy F_SETOWN_EX.
F_SETOWN_EX (struct f_owner_ex *) (od Linuksa 2.6.32)
Operacja przeprowadza podobne zadanie do F_SETOWN. Pozwala wywołującemu, na kierowanie sygnałów o
dostępności wejścia/wyjścia do określonego wątku, procesu lub grupy procesu. Wywołujący określa
cel sygnału za pomocą arg, wskaźnika do struktury f_owner_ex. Pole type ma jedną z następujących
wartości, definiujących sposób interpretacji pid:
F_OWNER_TID
Wysyła sygnał do wątku, którego identyfikator wątku (taki, jak zwracany przez wywołanie
clone(2) lub gettid(2)) podano w pid.
F_OWNER_PID
Wysyła sygnał do procesu, którego identyfikator podano w pid.
F_OWNER_PGRP
Wysyła sygnał do grupy procesu, której identyfikator podano w pid (proszę zauważyć, że w
przeciwieństwie do F_SETOWN, identyfikator grupy procesu jest tu podawany jako wartość
dodatnia).
F_GETSIG (void)
Zwraca (jako wynik funkcji) sygnał wysyłany, gdy wejście lub wyjście stanie się możliwe. Wartość
zerowa oznacza wysyłanie SIGIO. Dowolna inna wartość (łącznie z SIGIO) stanowi numer sygnału
wysyłanego zamiast niego. W tych sytuacjach dodatkowe informacje mogą być dostępne dla programu
obsługi sygnału, o ile zostały zainstalowane z użyciem SA_SIGINFO. arg jest ignorowane.
F_SETSIG (int)
Ustawia sygnał wysyłany, gdy wejście lub wyjście stanie się możliwe na wartość podaną w arg.
Wartość zerowa oznacza wysyłanie sygnału domyślnego, czyli SIGIO. Dowolna inna wartość (łącznie z
SIGIO) stanowi numer sygnału wysyłanego zamiast niego. W tych sytuacjach dodatkowe informacje mogą
być dostępne dla programu obsługi sygnału, o ile zostały zainstalowane z użyciem SA_SIGINFO.
Za pomocą F_SETSIG z niezerową wartością i przy ustawionym SA_SIGINFO dla programu obsługi sygnału
(patrz sigaction(2)), można przekazać do programu obsługi sygnału w strukturze siginfo_t dodatkowe
informacje o zdarzeniach wejścia/wyjścia. Jeśli pole si_code wskazuje, że źródłem jest SI_SIGIO,
to pole si_fd zawiera deskryptor pliku związany ze zdarzeniem. W przeciwnym przypadku, brak jest
wskazania, które deskryptory plików oczekują i do określenia dostępnych dla wejścia/wyjścia
deskryptorów plików należy używać zwykłych mechanizmów (select (2), poll(2), read(2) z ustawionym
O_NONBLOCK itd.).
Proszę zauważyć, że deskryptor pliku udostępniony w si_fd jest tym samym, który podano podczas
operacji F_SETSIG. To może prowadzić do nietypowej sytuacji. Gdy deskryptor pliku jest duplikowany
(dup(2) lub podobne), a pierwotny deskryptor pliku jest zamykany, to zdarzenie wejście/wyjścia
wciąż będzie tworzone, lecz pole si_fd będzie zawierać deskryptor już zamkniętego pliku.
Wybierając sygnał czasu rzeczywistego (wartość >= SIGRTMIN), można, używając tych samych numerów
sygnałów, spowodować umieszczenie w kolejce wielu zdarzeń wejścia/wyjścia (kolejkowanie zależy od
dostępnej pamięci). Jak powyżej, dodatkowe informacje są dostępne, gdy programy obsługi sygnałów
zostały zainstalowane z ustawionym SA_SIGINFO.
Proszę zauważyć, że Linux narzuca limit liczby sygnałów czasu rzeczywistego, które mogą oczekiwać
w kolejce na proces (zob. getrlimit(2) i signal(7)) i jeśli limit ten zostanie osiągnięty, to
jądro powraca do dostarczania SIGIO, a sygnał ten jest dostarczany do całego procesu, zamiast to
konkretnego wątku.
Za pomocą tych mechanizmów program może zaimplementować w pełni asynchroniczne wejście/wyjście, nie
używając przez większość czasu select(2) i poll(2).
Opisane powyżej korzystanie z O_ASYNC jest specyficzne dla BSD i Linuksa. Jedynym użyciem F_GETOWN i
F_SETOWN podanym w POSIX.1 jest użycie ich w połączeniu z sygnałem SIGURG na gniazdach (POSIX nie określa
sygnału SIGIO). F_GETOWN_EX, F_SETOWN_EX, F_GETSIG i F_SETSIG są typowo linuksowe. POSIX posiada
asynchroniczne wejście/wyjście i strukturę aio_sigevent służącą do podobnych celów; w Linuksie są one
również dostępne jako część biblioteki GNU C (glibc).
Dzierżawy
F_SETLEASE i F_GETLEASE (od Linuksa 2.4 wzwyż) służą do ustanowienia nowe dzierżawy i pobrania aktualnej
dzierżawy na opisie otwartego pliku, do którego odnosi się deskryptor pliku fd. Dzierżawa pliku zapewnia
mechanizm, w którym proces utrzymujący dzierżawę („dzierżawca”) jest zawiadamiany (poprzez dostarczenie
sygnału) o tym, że inny proces („zrywający dzierżawę”) próbuje wykonać open(2) lub truncate(2) na pliku,
do którego odnosi się dany deskryptor pliku.
F_SETLEASE (int)
Ustawia lub usuwa dzierżawę pliku w zależności od tego, która z następujących wartości zostanie
podana jako argument arg typu integer :
F_RDLCK
Ustanawia dzierżawę odczytu. Spowoduje to zawiadamianie procesu wywołującego o otwarciu
pliku do zapisu lub o obcinaniu go. Dzierżawa odczytu może zostać nałożona na deskryptor
pliku tylko wtedy, gdy jest on otwarty tylko do odczytu.
F_WRLCK
Ustanawia dzierżawę zapisu. Spowoduje to zawiadamianie wywołującego o otwarciu pliku do
odczytu lub do zapisu, lub o obcinaniu go. Dzierżawa zapisu może zostać nałożona na plik
tylko wtedy, gdy plik nie posiada żadnych innych otwartych deskryptorów pliku.
F_UNLCK
Zdejmuje własną dzierżawę z pliku.
Dzierżawy są związane z opisem otwartego pliku (zob. open(2)). Oznacza to, że zduplikowane deskryptory
pliku (utworzone np. za pomocą fork(2) lub dup(2)) odnoszą się do tej samem dzierżawy i można ją
zmodyfikować lub zwolnić za pomocą dowolnego z tych deskryptorów. Co więcej, dzierżawa jest zwalniana
przez operację F_UNLCK na dowolnym z tych zduplikowanych deskryptorów plików albo gdy wszystkie takie
deskryptory pliku zostaną zamknięte.
Dzierżawy można ustanawiać tylko na zwykłych plikach. Proces nieuprzywilejowany może ustanawiać jedynie
dzierżawy na plikach, których UID (właściciela) odpowiada UID-owi systemu plików dla danego procesu.
Proces z przywilejem CAP_LEASE (ang. capability) może ustanawiać dzierżawy na dowolnych plikach.
F_GETLEASE (void)
Wskazuje rodzaj dzierżawy związanej z deskryptorem pliku fd, zwracając F_RDLCK, F_WRLCK, albo
F_UNLCK, wskazując (odpowiednio) dzierżawę: odczytu, zapisu lub brak dzierżawy. arg jest
ignorowane.
Gdy proces („zrywający dzierżawę”) wykona operację open(2) lub truncate(2) kolidującą z dzierżawą
ustanowioną poprzez F_SETLEASE, wywołanie funkcji systemowej jest blokowane przez jądro, a jądro
zawiadamia dzierżawcę poprzez wysłanie sygnału (domyślnie SIGIO). Dzierżawca powinien odpowiedzieć na
otrzymanie tego sygnału wykonując porządki niezbędne dla przygotowania pliku do dostępu przez inny proces
(np. zrzucenie buforów) a następnie usunięcie lub zmniejszenie swojej dzierżawy. Dzierżawa jest usuwana
poprzez wykonanie operacji F_SETLEASE podając jako arg F_UNLCK. Jeśli dzierżawca aktualnie utrzymuje
dzierżawę zapisu na pliku, a zrywający dzierżawę otwiera plik do odczytu, to wystarczające jest
zmniejszenie dzierżawy przez dzierżawcę do dzierżawy odczytu. Dokonuje się tego poprzez wykonanie
operacji F_SETLEASE podając jako arg F_RDLCK.
Jeśli dzierżawca nie zmniejszy lub nie zwolni dzierżawy w ciągu podanej w /proc/sys/fs/lease-break-time
liczby sekund, to jądro przymusowo usunie lub zmniejszy dzierżawę dzierżawcy.
Po zainicjowaniu zerwania dzierżawy, F_GETLEASE zwraca docelowy typ dzierżawy (F_RDLCK albo F_UNLCK, w
zależności od tego, co byłoby zgodne ze zrywającym dzierżawę) do momentu, gdy dzierżawca dobrowolnie nie
zmniejszy lub nie zwolni dzierżawy albo do momentu, gdy jądro tego nie wymusi po upłynięciu czasu
zerwania dzierżawy.
Po dobrowolnym lub wymuszonym usunięciu lub zmniejszeniu dzierżawy, przy założeniu, że wywołanie funkcji
systemowej przez zrywającego dzierżawę nie jest nieblokujące, jądro pozwala na kontynuację funkcji
systemowej wywołanej przez zrywającego dzierżawę.
Jeśli zablokowane wywołanie open(2) lub truncate(2) zrywającego dzierżawę zostanie przerwane przez
procedurę obsługi sygnału, to wywołanie systemowe zawiedzie z błędem EINTR, lecz inne kroki opisane
wyżej, wciąż zostaną przeprowadzone. Jeśli zrywający dzierżawę zostanie zabity sygnałem w trakcie
blokowania open(2) lub truncate(2), to inne kroki opisane wyżej, wciąż zostaną przeprowadzone. Jeśli
zrywający dzierżawę poda znacznik O_NONBLOCK przy wywoływaniu open(2), to wywołanie zawiedzie natychmiast
z błędem EWOULDBLOCK, lecz inne kroki opisane wyżej, wciąż zostaną przeprowadzone.
Domyślnym sygnałem stosowanym do zawiadamiania dzierżawcy jest SIGIO, lecz można go zmienić za pomocą
operacji F_SETSIG w fcntl(). Jeśli wydano operację F_SETSIG (nawet podając SIGIO), a funkcja obsługi
sygnału została określona za pomocą SA_SIGINFO, to ta funkcja obsługi otrzyma jako drugi argument
strukturę siginfo_t, której pole si_fd będzie zawierać deskryptor pliku dzierżawionego pliku, do którego
uzyskuje dostęp inny proces (jest to przydatne, gdy wywołujący utrzymuje dzierżawy na wielu plikach).
Powiadamianie o zmianach pliku lub katalogu (dnotify)
F_NOTIFY (int)
(od Linuksa 2.4 wzwyż) Zapewnia powiadamianie o modyfikacji katalogu, do którego odnosi się fd lub
o modyfikacji któregokolwiek z plików w tym katalogu. Zdarzenia, powiadamianie o których ma
nastąpić, są określone w arg, będącym maską bitową utworzoną jako suma logiczna (OR) zera lub
więcej spośród następujących bitów:
DN_ACCESS
Uzyskano dostęp do pliku (read(2), pread(2), readv(2) i podobne)
DN_MODIFY
Plik został zmodyfikowany (write(2), pwrite(2), writev(2), truncate(2), ftruncate(2) i
podobne).
DN_CREATE
Utworzono plik (open(2), creat(2), mknod(2), mkdir(2), link(2), symlink(2), rename(2) w tym
katalogu).
DN_DELETE
Usunięto pliku (unlink(2), rename(2) do innego katalogu, rmdir(2)).
DN_RENAME
Zmieniono nazwę w obrębie katalogu (rename(2)).
DN_ATTRIB
Zmieniono atrybuty pliku (chown(2), chmod(2), utime(2), utimensat(2) i podobne).
(Uzyskanie tych definicji wymaga zdefiniowania makra sprawdzania cech _GNU_SOURCE przed włączeniem
jakichkolwiek plików nagłówkowych).
Powiadomienia dotyczące katalogów są zazwyczaj jednorazowe, więc aplikacja musi się ponownie
zarejestrować, aby otrzymać dalsze powiadomienia. Alternatywnie, jeśli w arg włączono
DN_MULTISHOT, to powiadomienia będą dokonywane aż do ich jawnego usunięcia.
Szereg wywołań podających DN_MULTISHOT kumuluje się, przy czym zdarzenia w arg są dodawane
logicznie do już monitorowanych. Aby wyłączyć powiadamianie o jakichkolwiek zdarzeniach, należy w
wywołaniu F_NOTIFY podać arg równe 0.
Powiadamianie odbywa się poprzez dostarczenie sygnału. Domyślnym sygnałem jest SIGIO, ale można go
zmienić za pomocą operacji F_SETSIG w fcntl() (proszę zauważyć, że SIGIO jest jednym z sygnałów
standardowych niepodlegających kolejkowaniu; przełączenie się na sygnały czasu rzeczywistego
oznacza, że do procesu może być kolejkowane wiele zawiadomień). W tym drugim przypadku, funkcja
obsługi sygnału otrzymuje jako swój drugi argument strukturę siginfo_t (gdy funkcja obsługi
sygnału została określona za pomocą SA_SIGINFO) a pole si_fd tej struktury zawiera deskryptor
pliku, który spowodował powiadomienie (przydatne, gdy utrzymywane są dzierżawy na wielu
katalogach).
W szczególności, gdy używa się DN_MULTISHOT, do zawiadamiania powinien być stosowany sygnał czasu
rzeczywistego, tak aby można było kolejkować wiele zmian.
UWAGA: Nowe aplikacje powinny korzystać z interfejsu inotify (dostępnego od Linuksa 2.6.13), który
zapewnia o wiele lepszy interfejs do uzyskiwania powiadomień o zdarzeniach w systemie plików. Zob.
inotify(7).
Zmiana pojemności potoku
F_SETPIPE_SZ (int; od Linuksa 2.6.35)
Zmienia pojemność potoku, do którego odnosi się fd na co najmniej arg bajtów. Proces
nieuprzywilejowany może dostosować pojemność potoku na dowolną wartość pomiędzy systemowym
rozmiarem strony i limitem zdefiniowanym w /proc/sys/fs/pipe-max-size (zob. proc(5)). Próby
ustawienia pojemności potoku poniżej rozmiaru strony są po cichu zaokrąglane w górę, do rozmiaru
strony. Próby ustawienia przez proces nieuprzywilejowany rozmiaru potoku powyżej limitu
/proc/sys/fs/pipe-max-size prowadzą do błędu EPERM; proces uprzywilejowany (CAP_SYS_RESOURCE) może
przesłonić ten limit.
Przy przydzielaniu bufora dla potoku, jądro może użyć pojemności większej niż arg, gdy jest to
wygodne ze względu na implementację (w bieżącej implementacji, przydzielanie następuje do
następnej wielokrotności będącej potęgą dwójki, w stosunku do żądanego rozmiaru). Rzeczywista
ustawiona pojemność (w bajtach) jest zwracana jako wynik funkcji.
Próby ustawienia pojemności potoku poniżej aktualnie używanego rozmiaru bufora, używanego do
przechowywania jego danych, poskutkuje błędem EBUSY.
Proszę zauważyć, że ze względu na sposób, w jaki wykorzystywane są strony bufora potoku, przy
zapisywaniu danych do potoku, liczba możliwych do zapisanych bajtów może być mniejsza, niż jego
nominalny rozmiar, zależnie od rozmiaru zapisów.
F_GETPIPE_SZ (void; od Linuksa 2.6.35)
Zwraca (jako wynik funkcji) rozmiar potoku, do którego odnosi się fd.
Pieczętowanie pliku (ang. file sealing)
Pieczęcie pliku ograniczają zestaw dozwolonych operacji na danym pliku. Od momentu ustawienia pieczęci na
pliku, określony zestaw operacji na tym pliku zawiedzie z błędem EPERM. Taki plik określany jest jako
zapieczętowany (ang. sealed). Domyślny zestaw pieczęci zależy od typu pliku i systemu plików. Przegląd
pieczętowania plików, opis celowości i nieco przykładów kodu zawarto w podręczniku memfd_create(2).
Obecnie, pieczęcie pliku można zastosować tylko na deskryptorze pliku zwróconym przez memfd_create(2)
(jeśli użyto MFD_ALLOW_SEALING). W innych systemach plików, wszystkie operacje fcntl() działające na
pieczęciach zwrócą EINVAL.
Pieczęcie są właściwością i-węzła. Z tego powodu, wszystkie opisy otwartego pliku (OFD) odnoszące się do
tego samego i-węzła dzielą ten sam zestaw pieczęci. Co więcej, pieczęci nigdy nie można usunąć, można je
jedynie dodawać.
F_ADD_SEALS (int; od Linuksa 3.17)
Dodaje pieczęcie przekazane w argumencie arg, będącym maską bitową, do zestawu pieczęci i-węzła,
do którego odnosi się deskryptor pliku fd. Pieczęci nie można usunąć. Jeśli wywołanie się
powiedzie, pieczęcie są natychmiast stosowane przez jądro. Jeśli aktualny zestaw pieczęci obejmuje
F_SEAL_SEAL (zob. niżej), to wywołanie to zostanie odrzucone z błędem EPERM. Dodanie pieczęci,
która jest już ustawiona nie ma skutku, o ile nie ustawiono F_SEAL_SEAL. Do umieszczenia pieczęci,
deskryptor pliku fd musi być zapisywalny.
F_GET_SEALS (void; od Linuksa 3.17)
Zwraca (jako wynik funkcji) bieżący zestaw pieczęci i-węzła, do którego odnosi się fd. Jeśli nie
ma ustawionych pieczęci, zwracane jest 0. Jeśli plik nie obsługuje pieczętowania, zwracane jest
-1, a errno jest ustawiane na EINVAL.
Dostępne są następujące pieczęcie:
F_SEAL_SEAL
Jeśli ta pieczęć jest ustawiona, każde kolejne wywołanie fcntl() z F_ADD_SEALS zawiedzie z błędem
EPERM. Ta pieczęć zapobiega zatem wszelkim modyfikacjom samego zestawu pieczęci. Jeśli początkowy
zestaw pieczęci pliku obejmuje F_SEAL_SEAL, to powoduje to efektywne ustawienie stałego i
zablokowanego zestawu pieczęci.
F_SEAL_SHRINK
Jeśli ta pieczęć jest ustawiona, rozmiar przedmiotowego pliku nie może ulec zmniejszeniu. Dotyczy
to open(2) ze znacznikiem O_TRUNC, jak również truncate(2) i ftruncate(2). Jeśli spróbuje się
zmniejszyć zapieczętowany w ten sposób plik, wywołania te zawiodą z błędem EPERM. Zwiększenie
rozmiaru pliku jest wciąż możliwe.
F_SEAL_GROW
Jeśli ta pieczęć jest ustawiona, rozmiar przedmiotowego pliku nie może ulec zwiększeniu. Dotyczy
to zapisu za pomocą write(2) poza koniec pliku, truncate(2), ftruncate(2) oraz fallocate(2). Jeśli
spróbuje się zwiększyć zapieczętowany w ten sposób plik, wywołania te zawiodą z błędem EPERM.
Jeśli rozmiar pliku nie zmieni się lub ulegnie zmniejszeniu, opisywane wywołania będą działać
zgodnie z oczekiwaniami.
F_SEAL_WRITE
Jeśli ta pieczęć jest ustawiona, nie można modyfikować zawartości pliku. Proszę zwrócić uwagę, że
zmniejszenie lub zwiększenie rozmiaru pliku jest wciąż możliwe i dozwolone. Z tego względu,
pieczęć ta jest zwykle używana w połączeniu z innymi pieczęciami. Pieczęć wpływa na write(2) i
fallocate(2) (tylko w połączeniu ze znacznikiem FALLOC_FL_PUNCH_HOLE). Jeśli pieczęć jest
ustawiona, wywołania te zawiodą z błędem EPERM. Co więcej, utworzenie nowego wspólnego,
zapisywalnego przypisania pamięci za pomocą mmap(2) również zawiedzie z błędem EPERM.
Użycie operacji F_ADD_SEALS do ustawienia pieczęci F_SEAL_WRITE zawiedzie z błędem EBUSY, jeśli
istnieją zapisywalne, wspólne przypisania pamięci. Przed dodaniem tej pieczęci konieczne jest ich
odmapowanie. Ponadto, jeśli wobec pliku istnieją jakieś oczekujące asynchroniczne operacje
wejścia/wyjścia (io_submit(2)), to wszystkie pozostałe zapisy zostaną odrzucone.
F_SEAL_FUTURE_WRITE (od Linuksa 5.1)
Skutek zastosowania tej pieczęci jest podobny do F_SEAL_WRITE, lecz zawartość pliku można wciąż
zmodyfikować za pomocą wspólnych, zapisywalnych przypisań pamięci, które utworzono przed
ustawieniem pieczęci. Próba utworzenia nowego zapisywalnego przypisania na pliku za pomocą
mmap(2), zawiedzie z błędem EPERM. Podobnie, próba zapisu do pliku za pomocą write(2) również
zawiedzie z błędem EPERM.
Korzystając z tej pieczęci, proces może utworzyć bufor pamięci, który będzie mógł wciąż
modyfikować, dzieląc go jednocześnie na zasadzie „tylko do odczytu” z innymi procesami.
Wskazówki odczytu/zapisu pliku
Do poinformowania jądra o oczekiwanym, względnym czasie istnienia zapisów do danego i-węzła lub za pomocą
opisu otwartego pliku (OFD; więcej informacji o opisach otwartego pliku w podręczniku open(2)) można użyć
wskazówek czasu istnienia zapisu. W tym kontekście, pojęcie „czas istnienia zapisu” oznacza oczekiwany
czas, jaki dane będą istniały na nośniku, przed ich nadpisaniem lub usunięciem.
Aplikacja może korzystać z różnych, podanych niżej, wartości wskazówek, aby podzielić zapisy na różne
klasy zapisów, dzięki czemu wielu użytkowników lub aplikacji działających na stacji z pojedynczym
nośnikiem może zbierać swoje wejścia/wyjścia w spójny sposób. Jednak znaczniki te nie udostępniają
żadnego funkcjonalnego zachowania, a różne klasy wejścia/wyjścia mogą używać wskazówek o czasie trwania
zapisu w arbitralny sposób dopóki tylko wskazówki są stosowane konsekwentnie.
Do deskryptora fd można zastosować następujące operacje:
F_GET_RW_HINT (uint64_t *; od Linuksa 4.13)
Zwraca wartość wskazówki odczytu/zapisu powiązanej z i-węzłem, do którego odnosi się fd.
F_SET_RW_HINT (uint64_t *; od Linuksa 4.13)
Ustawia wartość wskazówki odczytu/zapisu powiązanej z i-węzłem, do którego odnosi się fd.
Wskazówka ta będzie istniała do momentu jej jawnej modyfikacji lub do momentu odmontowania
przedmiotowego systemu plików.
F_GET_FILE_RW_HINT (uint64_t *; od Linuksa 4.13)
Zwraca wartość wskazówki odczytu/zapisu powiązanej z opisem otwartego pliku (OFD), do którego
odnosi się fd.
F_SET_FILE_RW_HINT (uint64_t *; od Linuksa 4.13)
Ustawia wartość wskazówki odczytu/zapisu powiązanej z opisem otwartego pliku (OFD), do którego
odnosi się fd.
Jeśli opisowi otwartego pliku nie przypisano wskazówki odczytu/zapisu, powinien on użyć wartości
przypisanej i-węzłowi, jeśli taka istnieje.
Od Linuksa 4.13 prawidłowe są następujące wskazówki odczytu/zapisu:
RWH_WRITE_LIFE_NOT_SET
Nie ustawiono żadnej wskazówki. Jest to wartość domyślna.
RWH_WRITE_LIFE_NONE
Nie ustawiono wskazówki zapisu z danym plikiem lub i-węzłem.
RWH_WRITE_LIFE_SHORT
Oczekuje się, że dane zapisane do tego i-węzła lub za pomocą tego opisu otwartego pliku, będą
istniały krótko.
RWH_WRITE_LIFE_MEDIUM
Oczekuje się, że dane zapisane do tego i-węzła lub za pomocą tego opisu otwartego pliku, będą
istniały dłużej, niż dane zapisane ze wskazówką RWH_WRITE_LIFE_SHORT.
RWH_WRITE_LIFE_LONG
Oczekuje się, że dane zapisane do tego i-węzła lub za pomocą tego opisu otwartego pliku, będą
istniały dłużej, niż dane zapisane ze wskazówką RWH_WRITE_LIFE_MEDIUM.
RWH_WRITE_LIFE_EXTREME
Oczekuje się, że dane zapisane do tego i-węzła lub za pomocą tego opisu otwartego pliku, będą
istniały dłużej, niż dane zapisane ze wskazówką RWH_WRITE_LIFE_LONG.
Wszystkie wskazówki dotyczące zapisu są jedynie relatywne względem siebie i nie należy przypisywać im
bezwzględnego znaczenia.
WARTOŚĆ ZWRACANA
Wartość zwracana po pomyślnym zakończeniu funkcji zależy od operacji:
F_DUPFD
Nowy deskryptor pliku.
F_GETFD
Wartość znaczników deskryptora pliku.
F_GETFL
Wartość znaczników stanu pliku
F_GETLEASE
Typ dzierżawy ustanowionej na deskryptorze pliku.
F_GETOWN
Wartość właściciela deskryptora pliku.
F_GETSIG
Wartość sygnału wysłanego, gdy odczyt lub zapis staną się możliwe, lub zero, dla tradycyjnego
zachowania SIGIO.
F_GETPIPE_SZ
F_SETPIPE_SZ
Pojemność potoku.
F_GET_SEALS
Mapa bitowa identyfikująca pieczęcie, które ustawiono dla i-węzła, do którego odnosi się fd.
Wszystkie pozostałe operacje
Zero.
W razie wystąpienia błędu zwracane jest -1 i ustawiane errno wskazując błąd.
BŁĘDY
EACCES lub EAGAIN
Operacja uniemożliwiona przez blokady utrzymywane przez inne procesy.
EAGAIN Operacja jest zabroniona, gdyż plik został odwzorowany w pamięci przez inny proces.
EBADF fd nie jest deskryptorem otwartego pliku.
EBADF op wynosi F_SETLK lub F_SETLKW a tryb otwarcia deskryptora pliku nie odpowiada rodzajowi żądanej
blokady.
EBUSY op wynosi F_SETPIPE_SZ, a nowa pojemność potoku określona w arg jest mniejsza, niż przestrzeń
bufora aktualnie zajęta do przechowywania danych w potoku.
EBUSY op wynosi F_ADD_SEALS, arg zawiera F_SEAL_WRITE i istnieje zapisywalne, dzielone przypisanie
pliku, do którego odnosi się fd.
EDEADLK
Stwierdzono, że podana operacja F_SETLKW spowodowałoby zakleszczenie blokad.
EFAULT lock znajduje się poza dostępną dla użytkownika przestrzenią adresową.
EINTR op wynosi F_SETLKW lub F_OFD_SETLKW i operacja została przerwana sygnałem; zob. signal(7).
EINTR op wynosi F_GETLK, F_SETLK, F_OFD_GETLK lub F_OFD_SETLK, a operacja została przerwana przez
sygnał, zanim blokada została sprawdzona lub ustawiona. Najbardziej prawdopodobne podczas
blokowania zdalnego pliku (np. blokowanie przez NFS), ale czasami zdarza się lokalnie.
EINVAL Wartość podana w op nie jest rozpoznawana przez to jądro.
EINVAL op wynosi F_ADD_SEALS, a arg obejmuje nierozpoznany bit pieczęci.
EINVAL op wynosi F_ADD_SEALS lub F_GET_SEALS, a system plików zawierający i-węzeł, do którego odnosi się
fd, nie obsługuje pieczętowania.
EINVAL op wynosi F_DUPFD, a arg jest ujemny lub większy od maksymalnej dozwolonej wartości (więcej
informacji w opisie RLIMIT_NOFILE w podręczniku getrlimit(2)).
EINVAL op wynosi F_SETSIG, a arg nie jest dozwolonym numerem sygnału.
EINVAL op wynosi F_OFD_SETLK, F_OFD_SETLKW lub F_OFD_GETLK, a l_pid nie podano jako zero.
EMFILE op wynosi F_DUPFD, a osiągnięto już maksymalną liczbę otwartych deskryptorów plików na proces.
ENOLCK Zbyt wiele otwartych blokad segmentowych, tablica blokad jest pełna lub zawiódł protokół
blokowania zdalnego (np. dla blokad przez NFS).
ENOTDIR
W op podano F_NOTIFY, lecz fd nie odnosi się do katalogu.
EPERM op wynosi F_SETPIPE_SZ i osiągnięto miękki lub sztywny limit potoku; zob. pipe(7).
EPERM Próbowano wyzerować znacznik O_APPEND na pliku posiadającym ustawiony atrybut „append-only”.
EPERM op wynosiło F_ADD_SEALS, lecz fd nie był otwarty do zapisu albo bieżący zestaw pieczęci już
obejmuje F_SEAL_SEAL.
STANDARDY
POSIX.1-2008.
F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE i
F_SETLEASE są typowo linuksowe (należy zdefiniować makro _GNU_SOURCE aby pozyskać te definicje).
F_OFD_SETLK, F_OFD_SETLKW i F_OFD_GETLK są typowo linuksowe (i konieczne jest zdefiniowanie _GNU_SOURCE
do pozyskania ich definicji), lecz trwają prace nad włączeniem ich do następnej wersji POSIX.1.
F_ADD_SEALS i F_GET_SEALS są typowo linuksowe.
HISTORIA
SVr4, 4.3BSD, POSIX.1-2001.
Jedynie operacje F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK i F_SETLKW są określone w
POSIX.1-2001.
F_GETOWN i F_SETOWN są określone w POSIX.1-2001 (do pozyskania ich definicji konieczne jest zdefiniowanie
_XOPEN_SOURCE z wartością 500 lub większą albo _POSIX_C_SOURCE z wartością 200809L lub większą).
F_DUPFD_CLOEXEC jest określone w POSIX.1-2008 (do pozyskania jego definicji konieczne jest zdefiniowanie
_POSIX_C_SOURCE z wartością 200809L lub większą albo _XOPEN_SOURCE z wartością 700 lub większą).
UWAGI
Błędy zwracane przez dup2(2) są inne niż zwracane przez F_DUPFD.
Blokowanie plików
Pierwotne linuksowe wywołanie systemowego fcntl() nie było zaprojektowane do obsługi dużych przesunięć
plików (w strukturze flock). W konsekwencji, Linux 2.4 dodał wywołanie systemowe fcntl64(). Nowsze
wywołanie systemowe korzysta z odmiennej struktury do blokowania plików, flock64 i odpowiadających
operacji, F_GETLK64, F_SETLK64 i F_SETLKW64. Detale te mogą być jednak zignorowane przez aplikacje
używające glibc, ponieważ jej funkcja opakowująca fcntl() obsługuje nowsze wywołanie systemowe, gdy tylko
jest dostępne, w sposób przezroczysty.
Blokady rekordów
Od Linuksa 2.0, nie ma oddziaływania pomiędzy typami blokad zakładanych przez flock(2) i przez fcntl().
W niektórych systemach struktura struct flock zawiera dodatkowe pola, takie jak np. l_sysid (do
identyfikacji komputera, na którym utrzymywana jest blokada). Oczywiście, samo l_pid jest mało przydatne,
gdy proces utrzymujący blokadę może działać na innym komputerze; w Linuksie, choć pole to jest obecne na
niektórych architekturach (np. MIPS32), to jednak nie jest używane.
Pierwotne linuksowe wywołanie systemowego fcntl() nie było zaprojektowane do obsługi dużych przesunięć
plików (w strukturze flock). W konsekwencji, Linux 2.4 dodał wywołanie systemowe fcntl64(). Nowsze
wywołanie systemowe korzysta z odmiennej struktury do blokowania plików, flock64 i odpowiadających
operacji, F_GETLK64, F_SETLK64 i F_SETLKW64. Detale te mogą być jednak zignorowane przez aplikacje
używające glibc, ponieważ jej funkcja opakowująca fcntl() obsługuje nowsze wywołanie systemowe, gdy tylko
jest dostępne, w sposób przezroczysty.
Blokowanie rekordów i NFS
Przed Linuksem 3.12, jeśli klient NFSv4 utraci kontakt z serwerem na pewien czas (zdefiniowany jako ponad
90 sekund bez żadnej komunikacji), to może utracić i odzyskać blokadę bez uświadamiania sobie tego faktu
(czas, po którym przyjmuje się utratę połączenia jest znany jako czas dzierżawy NFSv4 (leasetime); na
serwerze NFS można go sprawdzić w pliku /proc/fs/nfsd/nfsv4leasetime, który podaje go w sekundach;
domyślną wartością w pliku jest 90). Ten scenariusz grozi uszkodzeniem danych, ponieważ inny proces mógł
w międzyczasie posiąść blokadę i dokonać operacji wejścia/wyjścia na pliku.
Od Linuksa 3.12, jeśli klient NFSv4 utraci połączenie z serwerem, każda operacja wejścia/wyjścia na
pliku, przez proces który „sądzi”, że utrzymuje blokadę zawiedzie, dopóki ten proces nie zamknie i nie
otworzy pliku ponownie. Można ustawić parametr jądra nfs.recover_lost_locks na 1, aby powrócić do
zachowania sprzed wersji 3.12, gdy klient próbuje odzyskać zagubione blokady po odzyskaniu połączenia z
serwerem. Ze względu na towarzyszące temu ryzyko uszkodzenia danych, domyślnie parametr ten wynosi 0
(jest wyłączony).
USTERKI
F_SETFL
Nie da się użyć F_SETFL do zmiany statusu znaczników O_DSYNC i O_SYNC. Takie próby zostaną po cichu
zignorowane.
F_GETOWN
Ograniczenie konwencji linuksowego wywołania systemowego na niektórych architekturach (przede wszystkim
i386) oznacza, że jeśli (ujemny) identyfikator grupy procesu mający być zwrócony przez F_GETOWN znajduje
się w przedziale od -1 do -4095, to zwracana wartość jest przez glibc nieprawidłowo interpretowana jako
błąd w wywołaniu systemowym; to jest zwrócona przez fcntl() wartość będzie wynosiła -1, a errno będzie
zawierać (dodatni) identyfikator grupy procesu. Typowo linuksowa operacja F_GETOWN_EX unika tego
problemu. Od glibc 2.11, glibc czyni problem jądra F_GETOWN niewidzialnym, przez zaimplementowanie
F_GETOWN za pomocą F_GETOWN_EX.
F_SETOWN
W Linuksie 2.4 i wcześniejszych istnieje błąd, który może się ujawnić, gdy proces nieuprzywilejowany
używa F_SETOWN do podania właściciela deskryptora pliku gniazda, będące procesem (grupą) inną niż
wywołujący. W tym przypadku fcntl() może zwrócić -1 z errno ustawionym na EPERM nawet wówczas, gdy
właściciel procesu (grupy) był tym, do którego wywołujący ma prawo wysyłania sygnałów. Pomimo zwracania
błędu, własność deskryptora pliku jest ustawiana, a sygnały będą wysyłane do właściciela.
Wykrywanie zakleszczeń
Algorytm wykrywania zakleszczeń używany przez jądro przy przetwarzaniu żądań F_SETLKW może skutkować
wykryciami zarówno fałszywie negatywnymi (niewykryciem zakleszczeń, pozostawiając zestaw zakleszczonych
procesów stale zablokowanymi), jak i fałszywie pozytywnymi (błąd EDEADLK, gdy zakleszczenie nie
występuje). Przykładowo, jądro ogranicza głębokość poszukiwania zależności blokad do 10 kroków co
oznacza, że łańcuch kolistych zakleszczeń większy od tego rozmiaru nie zostanie wykryty. Dodatkowo, jądro
może nieprawidłowo wskazywać zakleszczenie, gdy dwa lub więcej procesów utworzonych za pomocą znacznika
CLONE_FILES z clone(2), wyglądają (dla jądra) na będące w konflikcie.
Blokowanie obowiązujące (przymusowe)
Linuksowa implementacja blokowania obowiązującego (przymusowego) jest podatna na sytuację wyścigu, co
czyni ją nierzetelną: wywołanie write(2), które nachodzi na blokadę może zmodyfikować dane po uzyskaniu
blokady, wywołanie read(2) które nachodzi na blokadę może wykryć zmianę danych, dokonaną jedynie po
uzyskaniu blokady zapisu. Podobny wyścig istnieje pomiędzy blokadami obowiązującymi a mmap(2). Z tego
powodu nie należy polegać na blokowaniu obowiązującym.
ZOBACZ TAKŻE
dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7), lslocks(8)
locks.txt, mandatory-locking.txt i dnotify.txt w katalogu Documentation/filesystems/ źródeł jądra Linux
(w starszych jądrach pliki te znajdują się bezpośrednio w katalogu Documentation/, a plik
mandatory-locking.txt ma nazwę mandatory.txt)
TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz
<ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>
Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać
zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ
ODPOWIEDZIALNOŚCI.
Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-
list@lists.sourceforge.net.
Linux man-pages 6.9.1 2 maja 2024 r. fcntl(2)