fcntl(2) System Calls Manual fcntl(2) NAZWA fcntl - manipuluje deskryptorem pliku BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include int fcntl(int fd, int op, ... /* arg */ ); OPIS fcntl dokonuje jednej z operacji opisanych ponizej na otwartym deskryptorze pliku fd. Wykonywana operacja jest okreslona przez op. fcntl() opcjonalnie moze przyjac trzeci argument. To, czy argument ten jest wymagany, zalezy od op. Wymagany typ argumentu jest wskazany w nawiasie po kazdej nazwie op (zwykle wymaganym typem jest int, a argument jest identyfikowany okresleniem arg) lub podane jest void, gdy argument nie jest wymagany. Niektore z ponizszych operacji sa obslugiwane jedynie w okreslonej wersji jadra Linux. Preferowana metoda sprawdzenia, czy dzialajace aktualnie jadro obsluguje dana operacje, jest przywolanie fcntl() z dana wartoscia op i sprawdzenie, czy wywolanie zawiedzie z bledem EINVAL wskazujac, ze jadro nie rozpoznalo tej wartosci. Duplikowanie deskryptora pliku F_DUPFD (int) Duplikuje deskryptor pliku fd za pomoca najnizszego dostepnego numeru deskryptora pliku wiekszego lub rownego arg. Rozni sie to od dup2(2), korzystajacego z konkretnego, zadanego deskryptora. Po pomyslnym zakonczeniu zwracany jest nowy deskryptor pliku. Wiecej informacji znajduje sie w podreczniku dup(2). F_DUPFD_CLOEXEC (int; od Linuksa 2.6.24) Jak w przypadku F_DUPFD, lecz dodatkowo ustawia znacznik zamkniecia-przy-wykonaniu dla duplikowanego deskryptora pliku. Podanie tego znacznika umozliwia programowi na unikniecie dodatkowej operacji F_SETFD fcntl(), w celu ustawienia znacznika FD_CLOEXEC. Wyjasnienie powodu, dla ktorego znacznik ten jest przydatny, znajduje sie w opisie O_CLOEXEC w podreczniku open(2). Znaczniki deskryptora pliku Nastepujace operacje kontroluja znaczniki powiazane z deskryptorem pliku. Obecnie zdefiniowano jedynie jeden taki znacznik: FD_CLOEXEC, znacznik zamkniecia-przy-wykonaniu. Jesli ustawiony jest bit FD_CLOEXEC, to deskryptor pliku zostanie automatycznie zamkniety podczas pomyslnego wykonania execve(2) (jesli execve(2) zawiedzie, deskryptor pliku jest pozostawiany otwarty). Jesli 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 wartosc okreslona w arg. W programach wielowatkowych, uzycie F_SETFD fcntl() do ustawienia znacznika zamkniecia przy uruchomieniu w tym samym czasie, w ktorym inny watek wykonuje fork(2) i execve(2) jest narazone na wystapienie sytuacji wyscigu, ktora moze niezamierzenie prowadzic do wycieku deskryptora pliku do programu wykonujacego proces potomny. Szczegoly i sposob na unikniecie tego problemu opisano przy znaczniku O_CLOEXEC, w podreczniku open(2). Znaczniki stanu pliku Z kazdym opisem otwartego pliku stowarzyszonych jest kilka znacznikow inicjowanych przez open(2), ktore moga ewentualnie byc modyfikowane przez fcntl(2). Zduplikowane deskryptory pliku (utworzone za pomoca dup(2), fork(2), itp.) odnosza sie do tego samego opisu otwartego pliku, dzielac zatem te same znaczniki stanu pliku. Znaczniki stanu pliku i ich znaczenie sa opisane w open(2). F_GETFL (void) Zwraca (jako wynik funkcji) tryb dostepu do pliku i znaczniki stanu pliku, arg jest ignorowany. F_SETFL (int) Ustawia znaczniki stanu pliku na wartosci okreslone przez arg. W arg ignorowane sa: tryb dostepu 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 moze zmienic jedynie znaczniki O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME i O_NONBLOCK. Nie da sie zmienic znacznikow O_DSYNC i O_SYNC; zob. USTERKI nizej. Blokowanie doradcze rekordow Linux implementuje tradycyjne (,,powiazane z procesem") blokady rekordow UNIX, zgodnie ze standardem POSIX. Istnieje rowniez typowo linuksowa alternatywa uzywajaca lepszej semantyki -- blokady opisow otwartego pliku, ktore sa opisane nieco nizej. F_SETLK, F_SETLKW i F_GETLK sluza do zakladania, zwalniania i sprawdzania obecnosci blokad rekordow (znanych rowniez jako blokady zakresu bajtow, segmentow pliku lub obszarow pliku). Trzeci argument, lock, jest wskaznikiem do struktury zawierajacej co najmniej nastepujace pola (kolejnosc nie jest okreslona). struct flock { ... short l_type; /* Rodzaj blokady: F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence; /* Sposob interpretacji l_start: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* Poczatek (przesuniecie) blokady */ off_t l_len; /* Liczba blokowanych bajtow */ pid_t l_pid; /* PID procesu uniemozliwiajacego blokade (ustawiane przez F_GETLK i F_OFD_GETLK) */ ... }; Pola l_whence, l_start i l_len w tej strukturze okreslaja zakres bajtow, ktore maja ulec zablokowaniu. Bajty po koncu pliku moga byc blokowane, nie moga to byc natomiast bajty przed jego poczatkiem. l_start jest poczatkowym przesunieciem blokady i jest interpretowane w odniesieniu do: poczatku pliku (gdy l_whence wynosi SEEK_SET), biezacego przesuniecia pliku (gdy l_whence wynosi SEEK_CUR) albo konca pliku (gdy l_whence wynosi SEEK_END). W ostatnich dwoch przypadkach, l_start moze byc liczba ujemna zakladajac, ze przesuniecie nie prowadzi przed poczatek pliku. l_len okresla liczbe bajtow do zablokowania. Jesli l_len jest dodatnie, to przedzial do zablokowania pokrywa bajty od l_start do l_start+l_len-1 wlacznie. Podanie 0 w l_len ma specjalne znaczenie: blokowane sa wszystkie bajty od polozenia okreslonego przez l_whence i l_start, az do konca pliku, niezaleznie od tego, jak duzy staje sie plik. POSIX.1-2001 zezwala implementacji (lecz tego nie wymaga) na obsluge ujemnych wartosci l_len; jesli l_len jest ujemna, to przedzial, ktorego dotyczy lock obejmuje bajty od l_start+l_len do l_start-1 wlacznie. Jest to obslugiwane od Linuksa 2.4.21 i Linuksa 2.5.49. Pole l_type moze sluzyc do zalozenia blokady dla odczytu (F_RDLCK) lub dla zapisu (F_WRLCK) do pliku. Dowolna liczba procesow moze utrzymywac blokade dla odczytu pliku (blokada wspolna) w pewnym jego obszarze, ale tylko jeden proces moze utrzymywac blokade dla zapisu do pliku (blokada wylaczna). Blokada wylaczna wyklucza wszelkie inne blokady, zarowno wspolne, jak i wylaczne. Pojedynczy proces moze w danym obszarze pliku utrzymywac blokade tylko jednego rodzaju; gdy w aktualnie zablokowanym obszarze zakladana jest nowa blokada, to istniejaca blokada jest przeksztalcana w blokade nowego typu (takie przeksztalcenie moze pociagac za soba podzial, skrocenie lub polaczenie z istniejaca blokada, gdy zakres bajtow podany dla nowej blokady nie pokrywa sie dokladnie z zakresem istniejacej blokady). F_SETLK (struct flock *) Ustawienie blokady dla zakresu bajtow okreslonego przez pola l_whence, l_start i l_len lock (gdy l_type jest rowne F_RDLCK lub F_WRLCK) albo jej zwolnienie (gdy l_type jest rowne F_UNLCK). Jesli kolidujaca blokada jest utrzymywana przez inny proces, funkcja ta zwraca -1 i ustawia errno na EACCES lub EAGAIN (zwracany w tym przypadku blad rozni sie pomiedzy implementacjami, dlatego POSIX wymaga sprawdzania przez przenosne aplikacje obu wartosci bledow). F_SETLKW (struct flock *) Podobne do F_SETLK, lecz w sytuacji, gdy na pliku zalozona jest kolidujaca blokada czeka na zwolnienie tej blokady. Jesli podczas oczekiwania zostanie przechwycony sygnal, funkcja jest przerywana i (po powrocie z funkcji obslugi sygnalu) powraca natychmiast (zwracajac wartosc -1 i ustawiajac errno na EINTR; zob. signal(7)). F_GETLK (struct flock *) Jako argument lock tej funkcji okresla blokade, jaka chcielibysmy zalozyc na pliku. Gdy zalozenie blokady jest mozliwe, fcntl() w rzeczywistosci jej nie zaklada, lecz zwraca F_UNLCK w polu l_type struktury lock pozostawiajac inne pola tej struktury niezmienione. Jesli jedna lub wiecej niezgodnych blokad zapobiegloby umieszczeniu tej blokady, to fcntl() zwroci szczegoly o jednej z tych blokad w polach l_type, l_whence, l_start i l_len w lock. Jesli niezgodna blokada jest tradycyjna (zwiazana z procesem) blokada rekordu, to pole l_pid jest ustawiane na PID procesu utrzymujacego te blokade. Jesli niezgodna blokada jest blokada opisu otwartego pliku (OFD), to l_pid jest ustawiane na -1. Prosze zauwazyc, ze w momencie sprawdzenia zwracanych informacji przez wywolujacego, moga byc juz one nieaktualne. Aby zalozyc blokade do odczytu, deskryptor fd musi byc otwarty do odczytu. Aby zalozyc blokade do zapisu, deskryptor fd musi byc otwarty do zapisu. Aby zalozyc obydwa rodzaje blokad, nalezy otworzyc plik do odczytu i zapisu. Przy umieszczaniu blokady z F_SETLKW, jadra wykrywa zakleszczenia, gdy zadania blokad dwoch lub wiecej procesow sa wzajemnie zablokowane przez blokady utrzymywane przez inne procesy. Przykladowo, przypuscmy, ze proces A utrzymuje blokade zapisu na bajcie 100. pliku, a proces B utrzymuje blokade zapisu na bajcie 200. Jesli kazdy z procesow sprobuje nastepnie zablokowac bajt juz zablokowany przez drugie proces za pomoca F_SETLKW, to -- bez wykrywania zakleszczen -- oba procesy pozostalyby stale zablokowane. Jesli jadro wykryje takie zakleszczenie, to spowoduje natychmiastowe niepowodzenie jednego z zadan blokady, z bledem EDEADLK; aplikacja napotykajaca na taki blad powinna zwolnic niektore ze swoich blokad, aby pozwolic dzialac inny aplikacjom, przed ponowna proba odzyskania wymaganych blokad. Wykrywane sa rowniez koliste zakleszczenia, z wiecej niz dwoma procesami. Prosze jednak zauwazyc, ze algorytm wykrywania zakleszczen jadra ma swoje ograniczenia, zob. USTERKI. Oprocz usuniecia za pomoca wyraznego F_UNLCK, blokady rekordow sa zwalniane automatycznie po zakonczeniu procesu. Blokady rekordow nie sa dziedziczone przez procesy potomne poprzez fork(2), ale sa zachowywane poprzez execve(2). Ze wzgledu na wykonywane przez biblioteke stdio(3) buforowanie, nalezy unikac blokowania rekordow w polaczeniu z funkcjami z tego pakietu; zamiast tego nalezy uzywac read(2) i write(2). Opisane wyzej blokady rekordow sa zwiazane z procesem (w przeciwienstwie do blokad opisu otwartego pliku, opisanych nizej). Ma to pewne niefortunne konsekwencje: o Jesli proces zamknie dowolny deskryptor odnoszacy sie do pliku, to zwalniane sa wszystkie blokady, niezaleznie od tego, na ktorym z deskryptorow pliku blokady te uzyskano. Jest to zle: oznacza, ze proces moze utracic swe blokady na pliku takim jak /etc/passwd lub /etc/mtab gdy jakas funkcja biblioteczna zdecyduje sie z jakiegos powodu otworzyc, odczytac i zamknac ten sam plik. o Watki procesu dziela blokady. Innymi slowy, program wielowatkowy nie moze korzystac z blokad rekordow, aby uniemozliwic jednoczesny dostep do tego samego miejsca pliku przez swoje watki. Blokady opisu otwartego pliku rozwiazuja oba te problemy. Blokady opisu otwartego pliku (spoza POSIX) Blokady opisu otwartego pliku sa blokadami doradczymi, definiowanymi w zakresie bajtow, ktorych dzialanie jest w wiekszosci identyczne do tradycyjnych blokad rekordow opisanych wyzej. Ten typ blokad jest typowo linuksowy i jest dostepny od Linuksa 3.15 (w Austin Group istnieje propozycja wlaczenia tego typu blokady do nastepnej rewizji POSIX.1). Wyjasnienie opisu otwartego pliku znajduje sie w podreczniku open(2). Podstawowa roznica, pomiedzy dwoma typami blokad jest fakt, ze o ile tradycyjne blokady rekordow sa zwiazane z procesem, to blokady opisu otwartego pliku sa zwiazane z opisem otwartego pliku, na ktorym je uzyskano, podobnie jak to wyglada w przypadku blokad uzyskanych za pomoca flock(2). W efekcie (inaczej niz przy tradycyjnych blokadach doradczych rekordow) blokady opisu otwartego pliku sa dziedziczone przy fork(2) (i clone(2) ze znacznikiem CLONE_FILES), a takze sa automatycznie zwalniane po ostatnim zamknieciu opisu otwartego pliku, zamiast zwalniania przy jakimkolwiek zamknieciu pliku. Kolidujace kombinacje blokad (tj. blokada odczytu z blokada zapisu lub dwie blokady zapisu) gdy jedna blokada jest blokada opisu otwartego pliku, a druga jest tradycyjna blokada rekordu prowadza do konfliktu nawet wowczas, gdy sa uzyskane przez ten sam proces na tym samym deskryptorze pliku. Blokady opisu otwartego pliku umieszczone na tym samym opisie otwartego pliku (tj. za pomoca tego samego deskryptora pliku lub za pomoca duplikatu deskryptora pliku utworzonego przez fork(2), dup(2), F_DUPFD z fcntl() itp.) sa zawsze kompatybilne: jesli nowa blokada jest umieszczona na juz zablokowanym rejonie pliku, to istniejace blokada jest konwertowana na nowy typ blokady (takie konwersje moga prowadzic to podzialu, zmniejszenia lub zlaczenia z dotychczasowa blokada, jak opisano to wyzej) Z drugiej strony, blokady opisu otwartego pliku moga byc w konflikcie, gdy sa uzyskane przez rozne opisy otwartego pliku. Z tego wzgledu, program wielowatkowy moze korzystac z blokad opisu otwartego pliku do synchronizowania dostepu do jakiegos miejsca w pliku, otwierajac (open(2)) plik z roznych watkow i zakladajac blokady za pomoca wynikowego deskryptora pliku. Podobnie jak w przypadku tradycyjnych blokad doradczych, trzeci argument do fcntl() -- lock, jest wskaznikiem do struktury flock. W odroznieniu do tradycyjnych blokad rekordow, pole l_pid tej struktury musi byc ustawione na zero za pomoca operacji opisanych nizej. Operacje dzialajace z blokadami opisu otwartego pliku sa analogiczne do tych uzywanych z tradycyjnymi blokadami: F_OFD_SETLK (struct flock *) Ustawia blokade opisu otwartego pliku (gdy l_type jest rowne F_RDLCK lub F_WRLCK) albo zwalnia blokade opisu otwartego pliku (gdy l_type jest rowne F_UNLCK) dla zakresu bajtow okreslonego przez pola l_whence, l_start i l_len lock. Jesli kolidujaca 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 zalozona jest kolidujaca blokada, czeka na zwolnienie tej blokady. Jesli podczas oczekiwania zostanie przechwycony sygnal, funkcja jest przerywana i (po powrocie z funkcji obslugi sygnalu) powraca natychmiast (zwracajac wartosc -1 i ustawiajac errno na EINTR; zob. signal(7)). F_OFD_GETLK (struct flock *) Jako argument lock tej funkcji okresla blokade opisu otwartego pliku, jaka chcielibysmy zalozyc na pliku. Gdy zalozenie blokady jest mozliwe, fcntl() w rzeczywistosci jej nie zaklada, lecz zwraca F_UNLCK w polu l_type struktury lock pozostawiajac inne pola tej struktury niezmienione. Jesli co najmniej jedna niezgodna blokada uniemozliwilaby zalozenie zadanej blokady, to informacje o jednej z tych blokad sa zwracane za pomoca lock, jak to opisano powyzej dla F_GETLK. W biezacej implementacji, dla blokad opisu otwartego pliku nie zachodzi wykrywanie zakleszczen (w odroznieniu od blokad rekordow zwiazanych z procesem, dla ktorych jadro wykonuje wykrywanie zakleszczen). Blokowanie obowiazujace (przymusowe) Ostrzezenie: linuksowa implementacja blokowania obowiazujacego jest zawodna (zob. USTERKI ponizej). Z powodu opisanych bledow i faktu, ze funkcjonalnosc ta nie byla czesto wykorzystywana, od Linuksa 4.5, tego typu blokowanie stalo sie opcjonalne i zalezy od ustawienia opcji konfiguracyjnej (CONFIG_MANDATORY_FILE_LOCKING). Od Linuksa 5.15 blokowanie obowiazujace (przymusowe) nie jest juz w ogolne obslugiwane. Domyslnie, zarowno tradycyjne blokady (zwiazane z procesem) jak i blokady opisu otwartego pliku (OFD) sa doradcze. Blokady doradcze nie sa wymuszane i sa przydatne tylko w przypadku wspoldzialajacych procesow. Oba te typy moga byc rowniez obowiazujace. Blokady obowiazujace sa wymuszane dla wszystkich procesow. Jesli proces sprobuje uzyskac niezgodny dostep (tj. odczyt -- read(2) lub zapis -- write(2)) w obszarze pliku, ktory posiada niezgodna blokade obowiazujaca, to wynik zalezy od tego, czy dla jego opisu otwartego pliku wlaczono znacznik O_NONBLOCK. Jesli znacznik O_NONBLOCK nie jest wlaczony, to dane wywolanie systemowe jest blokowane do momentu usuniecia blokady lub jej przeksztalcenia w tryb, ktory jest zgodny z uzyskiwanym dostepem. Jesli znacznik O_NONBLOCK jest wlaczony, to wywolanie systemowe zawodzi z bledem EAGAIN. Aby skorzystac z obowiazujacych blokad, blokowanie obowiazujace musi byc wlaczone zarowno na systemie plikow zawierajacym blokowany plik, jak i na samym pliku. Blokowanie obowiazujace w systemie plikow wlacza sie za pomoca opcji ,,-o mand" programu mount(8) lub za pomoca znacznika MS_MANDLOCK do mount(8). Blokowanie obowiazujace na pliku wlacza sie poprzez wylaczenie prawa uruchamiania dla grupy i wlaczenie bitu set-group-ID (zob. chmod(1) i chmod(2)). Blokowanie obowiazujace nie jest okreslone norma POSIX. Niektore inne systemy rowniez obsluguja blokowanie obowiazujace, choc szczegoly ich wlaczenia rowniez sie miedzy systemami. Zagubione blokady Gdy blokada doradcza jest uzyskiwana na sieciowym systemie plikow, takim jak NFS, mozliwe jest zagubienie blokady. Moze sie tak stac ze wzgledu na dzialanie administracyjne na serwerze lub z powodu podzialu sieci (tzn. utraty polaczenie z serwerem), ktore bedzie trwalo na tyle dlugo, ze serwer moze przyjac brak dalszego funkcjonowania przez klienta. Gdy system plikow stwierdzi, ze blokada zostala zagubiona, przyszly odczyt (read(2)) lub zapis (write(2)) moze zawiesc z bledem EIO. Blad ten bedzie wystepowal do momentu usuniecia blokady lub zamkniecia deskryptora pliku. Od Linuksa 3.12, dzieje sie tak przynajmniej w NFSv4 (we wszystkich jego pomniejszych wydaniach). Niektore wersje Uniksa wysylaja w takiej sytuacji sygnal (SIGLOST). Linux nie definiuje tego sygnalu i nie zapewnia zadnego asynchronicznego powiadamiania o zagubionych blokadach. Zarzadzanie sygnalami F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG i F_SETSIG sluza do zarzadzania sygnalami dostepnosci wejscia/wyjscia: F_GETOWN (void) Zwraca (jako wynik funkcji) identyfikator procesu lub identyfikator grupy procesow aktualnie otrzymujacych sygnaly SIGIO i SIGURG dla zdarzen na deskryptorze plikow fd. Identyfikatory procesow sa zwracane jako wartosci dodatnie, identyfikatory grupy procesow sa zwracane jako wartosci ujemne (lecz zob. USTERKI ponizej). arg jest ignorowane. F_SETOWN (int) Ustawia identyfikator procesu lub identyfikator grupy procesow aktualnie otrzymujacych sygnaly SIGIO i SIGURG dla zdarzen na deskryptorze plikow fd. Docelowy identyfikator procesu lub grupy procesow podaje sie jako arg. Identyfikator procesu jest okreslany jako liczba dodatnia; identyfikator grupy procesow jest okreslany za pomoca wartosci ujemnych. Najczesciej, proces wywolujacy okresla sie jako wlasciciel (tj. arg jest podawany jak przez getpid(2)). Oprocz ustawiania wlasciciela deskryptora pliku, konieczne jest rowniez wlaczenie generowania sygnalow na deskryptorze plikow. Mozna to uczynic za pomoca operacji F_SETFL fcntl(), ustawiajac znacznik stanu pliku O_ASYNC na deskryptorze pliku. Co za tym idzie, gdy tylko na deskryptorze pliku mozliwe stanie sie wejscie lub wyjscie, zostanie wyslany sygnal SIGIO. Operacje F_SETSIG fcntl() mozna wykorzystac do uzyskania dostarczenia sygnalu innego niz SIGIO. Wyslanie sygnalu do wlasciciela procesu (grupy) podanego w F_SETOWN, podlega takim samym sprawdzeniom uprawnien jak opisano w przypadku kill(2), gdy proces wysylajacy jest tym, ktory uzywa F_SETOWN (lecz zob. USTERKI ponizej). Jesli sprawdzenie uprawnien sie nie powiedzie, to sygnal jest po cichu odrzucany. Uwaga: Operacja F_SETOWN sprawdza poswiadczenia wywolujacego w chwili wywolania fcntl() i to te zapisane poswiadczenia sa uzywane do sprawdzenia uprawnien. Jesli deskryptor pliku fd odnosi sie do gniazda, F_SETOWN okresla rowniez odbiorce sygnalow SIGURG dostarczanych gdy poprzez gniazdo przybeda dane autonomiczne (SIGURG jest wysylany w sytuacjach, w ktorych select(2) zglosilby ,,stan wyjatkowy"). Nastepujacy akapit byl prawdziwy w Linuksie 2.6.x do Linuksa 2.6.11 wlacznie: Jesli F_SETSIG przekaze sie wartosc niezerowa w procesie wielowatkowym, dzialajacym z biblioteka watkowania obslugujaca grupy watkow (np. NPTL), to wartosc pozytywna przekazana F_SETOWN ma inne znaczenie: zamiast byciem identyfikatorem calego procesu, jest identyfikatorem watku, ktory identyfikuje dany watek procesu. W efekcie, moze byc konieczne podanie F_SETOWN wyniku gettid(2), zamiast wyniku getpid(2), aby uzyskac rozsadne wyniki, gdy korzysta sie z F_SETSIG (w biezacej, linuksowej implementacji watkowania, identyfikator glownego watku jest taki sam jak jego identyfikator procesu; oznacza to, ze programy jednowatkowe moga w tym scenariuszu korzystac z gettid(2) lub getpid(2)). Prosze jednak zauwazyc, ze stwierdzenie w tym akapicie nie dotyczy sygnalu SIGURG, wygenerowanego dla danych spoza pasma (ang. out-of-band data) na gniezdzie: ten sygnal zawsze trafia albo do procesu albo do grupy procesu, w zaleznosci od wartosci przekazanej F_SETOWN. Powyzsze zachowanie przypadkowo porzucono w Linuksie 2.6.12 i nie zostanie przywrocone. Od Linuksa 2.6.32, nalezy uzyc F_SETOWN_EX, aby przeznaczyc sygnaly SIGIO do okreslonego watku. F_GETOWN_EX (struct f_owner_ex *) (od Linuksa 2.6.32) Zwraca ustawienia aktualnego wlasciciela deskryptora pliku, jak zdefiniowane poprzednia operacja F_SETOWN_EX. Informacja ta jest zwracana przez strukture na ktora wskazuje arg, ktora ma postac: struct f_owner_ex { int type; pid_t pid; }; Pole type bedzie mialo jedna z wartosci: F_OWNER_TID, F_OWNER_PID lub F_OWNER_PGRP. Pole pid jest liczba dodatnia, reprezentujaca identyfikator, odpowiednio, watku, procesu lub grupy procesu. Wiecej 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 wywolujacemu, na kierowanie sygnalow o dostepnosci wejscia/wyjscia do okreslonego watku, procesu lub grupy procesu. Wywolujacy okresla cel sygnalu za pomoca arg, wskaznika do struktury f_owner_ex. Pole type ma jedna z nastepujacych wartosci, definiujacych sposob interpretacji pid: F_OWNER_TID Wysyla sygnal do watku, ktorego identyfikator watku (taki, jak zwracany przez wywolanie clone(2) lub gettid(2)) podano w pid. F_OWNER_PID Wysyla sygnal do procesu, ktorego identyfikator podano w pid. F_OWNER_PGRP Wysyla sygnal do grupy procesu, ktorej identyfikator podano w pid (prosze zauwazyc, ze w przeciwienstwie do F_SETOWN, identyfikator grupy procesu jest tu podawany jako wartosc dodatnia). F_GETSIG (void) Zwraca (jako wynik funkcji) sygnal wysylany, gdy wejscie lub wyjscie stanie sie mozliwe. Wartosc zerowa oznacza wysylanie SIGIO. Dowolna inna wartosc (lacznie z SIGIO) stanowi numer sygnalu wysylanego zamiast niego. W tych sytuacjach dodatkowe informacje moga byc dostepne dla programu obslugi sygnalu, o ile zostaly zainstalowane z uzyciem SA_SIGINFO. arg jest ignorowane. F_SETSIG (int) Ustawia sygnal wysylany, gdy wejscie lub wyjscie stanie sie mozliwe na wartosc podana w arg. Wartosc zerowa oznacza wysylanie sygnalu domyslnego, czyli SIGIO. Dowolna inna wartosc (lacznie z SIGIO) stanowi numer sygnalu wysylanego zamiast niego. W tych sytuacjach dodatkowe informacje moga byc dostepne dla programu obslugi sygnalu, o ile zostaly zainstalowane z uzyciem SA_SIGINFO. Za pomoca F_SETSIG z niezerowa wartoscia i przy ustawionym SA_SIGINFO dla programu obslugi sygnalu (patrz sigaction(2)), mozna przekazac do programu obslugi sygnalu w strukturze siginfo_t dodatkowe informacje o zdarzeniach wejscia/wyjscia. Jesli pole si_code wskazuje, ze zrodlem jest SI_SIGIO, to pole si_fd zawiera deskryptor pliku zwiazany ze zdarzeniem. W przeciwnym przypadku, brak jest wskazania, ktore deskryptory plikow oczekuja i do okreslenia dostepnych dla wejscia/wyjscia deskryptorow plikow nalezy uzywac zwyklych mechanizmow (select (2), poll(2), read(2) z ustawionym O_NONBLOCK itd.). Prosze zauwazyc, ze deskryptor pliku udostepniony w si_fd jest tym samym, ktory podano podczas operacji F_SETSIG. To moze prowadzic do nietypowej sytuacji. Gdy deskryptor pliku jest duplikowany (dup(2) lub podobne), a pierwotny deskryptor pliku jest zamykany, to zdarzenie wejscie/wyjscia wciaz bedzie tworzone, lecz pole si_fd bedzie zawierac deskryptor juz zamknietego pliku. Wybierajac sygnal czasu rzeczywistego (wartosc >= SIGRTMIN), mozna, uzywajac tych samych numerow sygnalow, spowodowac umieszczenie w kolejce wielu zdarzen wejscia/wyjscia (kolejkowanie zalezy od dostepnej pamieci). Jak powyzej, dodatkowe informacje sa dostepne, gdy programy obslugi sygnalow zostaly zainstalowane z ustawionym SA_SIGINFO. Prosze zauwazyc, ze Linux narzuca limit liczby sygnalow czasu rzeczywistego, ktore moga oczekiwac w kolejce na proces (zob. getrlimit(2) i signal(7)) i jesli limit ten zostanie osiagniety, to jadro powraca do dostarczania SIGIO, a sygnal ten jest dostarczany do calego procesu, zamiast to konkretnego watku. Za pomoca tych mechanizmow program moze zaimplementowac w pelni asynchroniczne wejscie/wyjscie, nie uzywajac przez wiekszosc czasu select(2) i poll(2). Opisane powyzej korzystanie z O_ASYNC jest specyficzne dla BSD i Linuksa. Jedynym uzyciem F_GETOWN i F_SETOWN podanym w POSIX.1 jest uzycie ich w polaczeniu z sygnalem SIGURG na gniazdach (POSIX nie okresla sygnalu SIGIO). F_GETOWN_EX, F_SETOWN_EX, F_GETSIG i F_SETSIG sa typowo linuksowe. POSIX posiada asynchroniczne wejscie/wyjscie i strukture aio_sigevent sluzaca do podobnych celow; w Linuksie sa one rowniez dostepne jako czesc biblioteki GNU C (glibc). Dzierzawy F_SETLEASE i F_GETLEASE (od Linuksa 2.4 wzwyz) sluza do ustanowienia nowe dzierzawy i pobrania aktualnej dzierzawy na opisie otwartego pliku, do ktorego odnosi sie deskryptor pliku fd. Dzierzawa pliku zapewnia mechanizm, w ktorym proces utrzymujacy dzierzawe (,,dzierzawca") jest zawiadamiany (poprzez dostarczenie sygnalu) o tym, ze inny proces (,,zrywajacy dzierzawe") probuje wykonac open(2) lub truncate(2) na pliku, do ktorego odnosi sie dany deskryptor pliku. F_SETLEASE (int) Ustawia lub usuwa dzierzawe pliku w zaleznosci od tego, ktora z nastepujacych wartosci zostanie podana jako argument arg typu integer : F_RDLCK Ustanawia dzierzawe odczytu. Spowoduje to zawiadamianie procesu wywolujacego o otwarciu pliku do zapisu lub o obcinaniu go. Dzierzawa odczytu moze zostac nalozona na deskryptor pliku tylko wtedy, gdy jest on otwarty tylko do odczytu. F_WRLCK Ustanawia dzierzawe zapisu. Spowoduje to zawiadamianie wywolujacego o otwarciu pliku do odczytu lub do zapisu, lub o obcinaniu go. Dzierzawa zapisu moze zostac nalozona na plik tylko wtedy, gdy plik nie posiada zadnych innych otwartych deskryptorow pliku. F_UNLCK Zdejmuje wlasna dzierzawe z pliku. Dzierzawy sa zwiazane z opisem otwartego pliku (zob. open(2)). Oznacza to, ze zduplikowane deskryptory pliku (utworzone np. za pomoca fork(2) lub dup(2)) odnosza sie do tej samem dzierzawy i mozna ja zmodyfikowac lub zwolnic za pomoca dowolnego z tych deskryptorow. Co wiecej, dzierzawa jest zwalniana przez operacje F_UNLCK na dowolnym z tych zduplikowanych deskryptorow plikow albo gdy wszystkie takie deskryptory pliku zostana zamkniete. Dzierzawy mozna ustanawiac tylko na zwyklych plikach. Proces nieuprzywilejowany moze ustanawiac jedynie dzierzawy na plikach, ktorych UID (wlasciciela) odpowiada UID-owi systemu plikow dla danego procesu. Proces z przywilejem CAP_LEASE (ang. capability) moze ustanawiac dzierzawy na dowolnych plikach. F_GETLEASE (void) Wskazuje rodzaj dzierzawy zwiazanej z deskryptorem pliku fd, zwracajac F_RDLCK, F_WRLCK, albo F_UNLCK, wskazujac (odpowiednio) dzierzawe: odczytu, zapisu lub brak dzierzawy. arg jest ignorowane. Gdy proces (,,zrywajacy dzierzawe") wykona operacje open(2) lub truncate(2) kolidujaca z dzierzawa ustanowiona poprzez F_SETLEASE, wywolanie funkcji systemowej jest blokowane przez jadro, a jadro zawiadamia dzierzawce poprzez wyslanie sygnalu (domyslnie SIGIO). Dzierzawca powinien odpowiedziec na otrzymanie tego sygnalu wykonujac porzadki niezbedne dla przygotowania pliku do dostepu przez inny proces (np. zrzucenie buforow) a nastepnie usuniecie lub zmniejszenie swojej dzierzawy. Dzierzawa jest usuwana poprzez wykonanie operacji F_SETLEASE podajac jako arg F_UNLCK. Jesli dzierzawca aktualnie utrzymuje dzierzawe zapisu na pliku, a zrywajacy dzierzawe otwiera plik do odczytu, to wystarczajace jest zmniejszenie dzierzawy przez dzierzawce do dzierzawy odczytu. Dokonuje sie tego poprzez wykonanie operacji F_SETLEASE podajac jako arg F_RDLCK. Jesli dzierzawca nie zmniejszy lub nie zwolni dzierzawy w ciagu podanej w /proc/sys/fs/lease-break-time liczby sekund, to jadro przymusowo usunie lub zmniejszy dzierzawe dzierzawcy. Po zainicjowaniu zerwania dzierzawy, F_GETLEASE zwraca docelowy typ dzierzawy (F_RDLCK albo F_UNLCK, w zaleznosci od tego, co byloby zgodne ze zrywajacym dzierzawe) do momentu, gdy dzierzawca dobrowolnie nie zmniejszy lub nie zwolni dzierzawy albo do momentu, gdy jadro tego nie wymusi po uplynieciu czasu zerwania dzierzawy. Po dobrowolnym lub wymuszonym usunieciu lub zmniejszeniu dzierzawy, przy zalozeniu, ze wywolanie funkcji systemowej przez zrywajacego dzierzawe nie jest nieblokujace, jadro pozwala na kontynuacje funkcji systemowej wywolanej przez zrywajacego dzierzawe. Jesli zablokowane wywolanie open(2) lub truncate(2) zrywajacego dzierzawe zostanie przerwane przez procedure obslugi sygnalu, to wywolanie systemowe zawiedzie z bledem EINTR, lecz inne kroki opisane wyzej, wciaz zostana przeprowadzone. Jesli zrywajacy dzierzawe zostanie zabity sygnalem w trakcie blokowania open(2) lub truncate(2), to inne kroki opisane wyzej, wciaz zostana przeprowadzone. Jesli zrywajacy dzierzawe poda znacznik O_NONBLOCK przy wywolywaniu open(2), to wywolanie zawiedzie natychmiast z bledem EWOULDBLOCK, lecz inne kroki opisane wyzej, wciaz zostana przeprowadzone. Domyslnym sygnalem stosowanym do zawiadamiania dzierzawcy jest SIGIO, lecz mozna go zmienic za pomoca operacji F_SETSIG w fcntl(). Jesli wydano operacje F_SETSIG (nawet podajac SIGIO), a funkcja obslugi sygnalu zostala okreslona za pomoca SA_SIGINFO, to ta funkcja obslugi otrzyma jako drugi argument strukture siginfo_t, ktorej pole si_fd bedzie zawierac deskryptor pliku dzierzawionego pliku, do ktorego uzyskuje dostep inny proces (jest to przydatne, gdy wywolujacy utrzymuje dzierzawy na wielu plikach). Powiadamianie o zmianach pliku lub katalogu (dnotify) F_NOTIFY (int) (od Linuksa 2.4 wzwyz) Zapewnia powiadamianie o modyfikacji katalogu, do ktorego odnosi sie fd lub o modyfikacji ktoregokolwiek z plikow w tym katalogu. Zdarzenia, powiadamianie o ktorych ma nastapic, sa okreslone w arg, bedacym maska bitowa utworzona jako suma logiczna (OR) zera lub wiecej sposrod nastepujacych bitow: DN_ACCESS Uzyskano dostep do pliku (read(2), pread(2), readv(2) i podobne) DN_MODIFY Plik zostal 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 Usunieto pliku (unlink(2), rename(2) do innego katalogu, rmdir(2)). DN_RENAME Zmieniono nazwe w obrebie 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 wlaczeniem jakichkolwiek plikow naglowkowych). Powiadomienia dotyczace katalogow sa zazwyczaj jednorazowe, wiec aplikacja musi sie ponownie zarejestrowac, aby otrzymac dalsze powiadomienia. Alternatywnie, jesli w arg wlaczono DN_MULTISHOT, to powiadomienia beda dokonywane az do ich jawnego usuniecia. Szereg wywolan podajacych DN_MULTISHOT kumuluje sie, przy czym zdarzenia w arg sa dodawane logicznie do juz monitorowanych. Aby wylaczyc powiadamianie o jakichkolwiek zdarzeniach, nalezy w wywolaniu F_NOTIFY podac arg rowne 0. Powiadamianie odbywa sie poprzez dostarczenie sygnalu. Domyslnym sygnalem jest SIGIO, ale mozna go zmienic za pomoca operacji F_SETSIG w fcntl() (prosze zauwazyc, ze SIGIO jest jednym z sygnalow standardowych niepodlegajacych kolejkowaniu; przelaczenie sie na sygnaly czasu rzeczywistego oznacza, ze do procesu moze byc kolejkowane wiele zawiadomien). W tym drugim przypadku, funkcja obslugi sygnalu otrzymuje jako swoj drugi argument strukture siginfo_t (gdy funkcja obslugi sygnalu zostala okreslona za pomoca SA_SIGINFO) a pole si_fd tej struktury zawiera deskryptor pliku, ktory spowodowal powiadomienie (przydatne, gdy utrzymywane sa dzierzawy na wielu katalogach). W szczegolnosci, gdy uzywa sie DN_MULTISHOT, do zawiadamiania powinien byc stosowany sygnal czasu rzeczywistego, tak aby mozna bylo kolejkowac wiele zmian. UWAGA: Nowe aplikacje powinny korzystac z interfejsu inotify (dostepnego od Linuksa 2.6.13), ktory zapewnia o wiele lepszy interfejs do uzyskiwania powiadomien o zdarzeniach w systemie plikow. Zob. inotify(7). Zmiana pojemnosci potoku F_SETPIPE_SZ (int; od Linuksa 2.6.35) Zmienia pojemnosc potoku, do ktorego odnosi sie fd na co najmniej arg bajtow. Proces nieuprzywilejowany moze dostosowac pojemnosc potoku na dowolna wartosc pomiedzy systemowym rozmiarem strony i limitem zdefiniowanym w /proc/sys/fs/pipe-max-size (zob. proc(5)). Proby ustawienia pojemnosci potoku ponizej rozmiaru strony sa po cichu zaokraglane w gore, do rozmiaru strony. Proby ustawienia przez proces nieuprzywilejowany rozmiaru potoku powyzej limitu /proc/sys/fs/pipe-max-size prowadza do bledu EPERM; proces uprzywilejowany (CAP_SYS_RESOURCE) moze przeslonic ten limit. Przy przydzielaniu bufora dla potoku, jadro moze uzyc pojemnosci wiekszej niz arg, gdy jest to wygodne ze wzgledu na implementacje (w biezacej implementacji, przydzielanie nastepuje do nastepnej wielokrotnosci bedacej potega dwojki, w stosunku do zadanego rozmiaru). Rzeczywista ustawiona pojemnosc (w bajtach) jest zwracana jako wynik funkcji. Proby ustawienia pojemnosci potoku ponizej aktualnie uzywanego rozmiaru bufora, uzywanego do przechowywania jego danych, poskutkuje bledem EBUSY. Prosze zauwazyc, ze ze wzgledu na sposob, w jaki wykorzystywane sa strony bufora potoku, przy zapisywaniu danych do potoku, liczba mozliwych do zapisanych bajtow moze byc mniejsza, niz jego nominalny rozmiar, zaleznie od rozmiaru zapisow. F_GETPIPE_SZ (void; od Linuksa 2.6.35) Zwraca (jako wynik funkcji) rozmiar potoku, do ktorego odnosi sie fd. Pieczetowanie pliku (ang. file sealing) Pieczecie pliku ograniczaja zestaw dozwolonych operacji na danym pliku. Od momentu ustawienia pieczeci na pliku, okreslony zestaw operacji na tym pliku zawiedzie z bledem EPERM. Taki plik okreslany jest jako zapieczetowany (ang. sealed). Domyslny zestaw pieczeci zalezy od typu pliku i systemu plikow. Przeglad pieczetowania plikow, opis celowosci i nieco przykladow kodu zawarto w podreczniku memfd_create(2). Obecnie, pieczecie pliku mozna zastosowac tylko na deskryptorze pliku zwroconym przez memfd_create(2) (jesli uzyto MFD_ALLOW_SEALING). W innych systemach plikow, wszystkie operacje fcntl() dzialajace na pieczeciach zwroca EINVAL. Pieczecie sa wlasciwoscia i-wezla. Z tego powodu, wszystkie opisy otwartego pliku (OFD) odnoszace sie do tego samego i-wezla dziela ten sam zestaw pieczeci. Co wiecej, pieczeci nigdy nie mozna usunac, mozna je jedynie dodawac. F_ADD_SEALS (int; od Linuksa 3.17) Dodaje pieczecie przekazane w argumencie arg, bedacym maska bitowa, do zestawu pieczeci i-wezla, do ktorego odnosi sie deskryptor pliku fd. Pieczeci nie mozna usunac. Jesli wywolanie sie powiedzie, pieczecie sa natychmiast stosowane przez jadro. Jesli aktualny zestaw pieczeci obejmuje F_SEAL_SEAL (zob. nizej), to wywolanie to zostanie odrzucone z bledem EPERM. Dodanie pieczeci, ktora jest juz ustawiona nie ma skutku, o ile nie ustawiono F_SEAL_SEAL. Do umieszczenia pieczeci, deskryptor pliku fd musi byc zapisywalny. F_GET_SEALS (void; od Linuksa 3.17) Zwraca (jako wynik funkcji) biezacy zestaw pieczeci i-wezla, do ktorego odnosi sie fd. Jesli nie ma ustawionych pieczeci, zwracane jest 0. Jesli plik nie obsluguje pieczetowania, zwracane jest -1, a errno jest ustawiane na EINVAL. Dostepne sa nastepujace pieczecie: F_SEAL_SEAL Jesli ta pieczec jest ustawiona, kazde kolejne wywolanie fcntl() z F_ADD_SEALS zawiedzie z bledem EPERM. Ta pieczec zapobiega zatem wszelkim modyfikacjom samego zestawu pieczeci. Jesli poczatkowy zestaw pieczeci pliku obejmuje F_SEAL_SEAL, to powoduje to efektywne ustawienie stalego i zablokowanego zestawu pieczeci. F_SEAL_SHRINK Jesli ta pieczec jest ustawiona, rozmiar przedmiotowego pliku nie moze ulec zmniejszeniu. Dotyczy to open(2) ze znacznikiem O_TRUNC, jak rowniez truncate(2) i ftruncate(2). Jesli sprobuje sie zmniejszyc zapieczetowany w ten sposob plik, wywolania te zawioda z bledem EPERM. Zwiekszenie rozmiaru pliku jest wciaz mozliwe. F_SEAL_GROW Jesli ta pieczec jest ustawiona, rozmiar przedmiotowego pliku nie moze ulec zwiekszeniu. Dotyczy to zapisu za pomoca write(2) poza koniec pliku, truncate(2), ftruncate(2) oraz fallocate(2). Jesli sprobuje sie zwiekszyc zapieczetowany w ten sposob plik, wywolania te zawioda z bledem EPERM. Jesli rozmiar pliku nie zmieni sie lub ulegnie zmniejszeniu, opisywane wywolania beda dzialac zgodnie z oczekiwaniami. F_SEAL_WRITE Jesli ta pieczec jest ustawiona, nie mozna modyfikowac zawartosci pliku. Prosze zwrocic uwage, ze zmniejszenie lub zwiekszenie rozmiaru pliku jest wciaz mozliwe i dozwolone. Z tego wzgledu, pieczec ta jest zwykle uzywana w polaczeniu z innymi pieczeciami. Pieczec wplywa na write(2) i fallocate(2) (tylko w polaczeniu ze znacznikiem FALLOC_FL_PUNCH_HOLE). Jesli pieczec jest ustawiona, wywolania te zawioda z bledem EPERM. Co wiecej, utworzenie nowego wspolnego, zapisywalnego przypisania pamieci za pomoca mmap(2) rowniez zawiedzie z bledem EPERM. Uzycie operacji F_ADD_SEALS do ustawienia pieczeci F_SEAL_WRITE zawiedzie z bledem EBUSY, jesli istnieja zapisywalne, wspolne przypisania pamieci. Przed dodaniem tej pieczeci konieczne jest ich odmapowanie. Ponadto, jesli wobec pliku istnieja jakies oczekujace asynchroniczne operacje wejscia/wyjscia (io_submit(2)), to wszystkie pozostale zapisy zostana odrzucone. F_SEAL_FUTURE_WRITE (od Linuksa 5.1) Skutek zastosowania tej pieczeci jest podobny do F_SEAL_WRITE, lecz zawartosc pliku mozna wciaz zmodyfikowac za pomoca wspolnych, zapisywalnych przypisan pamieci, ktore utworzono przed ustawieniem pieczeci. Proba utworzenia nowego zapisywalnego przypisania na pliku za pomoca mmap(2), zawiedzie z bledem EPERM. Podobnie, proba zapisu do pliku za pomoca write(2) rowniez zawiedzie z bledem EPERM. Korzystajac z tej pieczeci, proces moze utworzyc bufor pamieci, ktory bedzie mogl wciaz modyfikowac, dzielac go jednoczesnie na zasadzie ,,tylko do odczytu" z innymi procesami. Wskazowki odczytu/zapisu pliku Do poinformowania jadra o oczekiwanym, wzglednym czasie istnienia zapisow do danego i-wezla lub za pomoca opisu otwartego pliku (OFD; wiecej informacji o opisach otwartego pliku w podreczniku open(2)) mozna uzyc wskazowek czasu istnienia zapisu. W tym kontekscie, pojecie ,,czas istnienia zapisu" oznacza oczekiwany czas, jaki dane beda istnialy na nosniku, przed ich nadpisaniem lub usunieciem. Aplikacja moze korzystac z roznych, podanych nizej, wartosci wskazowek, aby podzielic zapisy na rozne klasy zapisow, dzieki czemu wielu uzytkownikow lub aplikacji dzialajacych na stacji z pojedynczym nosnikiem moze zbierac swoje wejscia/wyjscia w spojny sposob. Jednak znaczniki te nie udostepniaja zadnego funkcjonalnego zachowania, a rozne klasy wejscia/wyjscia moga uzywac wskazowek o czasie trwania zapisu w arbitralny sposob dopoki tylko wskazowki sa stosowane konsekwentnie. Do deskryptora fd mozna zastosowac nastepujace operacje: F_GET_RW_HINT (uint64_t *; od Linuksa 4.13) Zwraca wartosc wskazowki odczytu/zapisu powiazanej z i-wezlem, do ktorego odnosi sie fd. F_SET_RW_HINT (uint64_t *; od Linuksa 4.13) Ustawia wartosc wskazowki odczytu/zapisu powiazanej z i-wezlem, do ktorego odnosi sie fd. Wskazowka ta bedzie istniala do momentu jej jawnej modyfikacji lub do momentu odmontowania przedmiotowego systemu plikow. F_GET_FILE_RW_HINT (uint64_t *; od Linuksa 4.13) Zwraca wartosc wskazowki odczytu/zapisu powiazanej z opisem otwartego pliku (OFD), do ktorego odnosi sie fd. F_SET_FILE_RW_HINT (uint64_t *; od Linuksa 4.13) Ustawia wartosc wskazowki odczytu/zapisu powiazanej z opisem otwartego pliku (OFD), do ktorego odnosi sie fd. Jesli opisowi otwartego pliku nie przypisano wskazowki odczytu/zapisu, powinien on uzyc wartosci przypisanej i-wezlowi, jesli taka istnieje. Od Linuksa 4.13 prawidlowe sa nastepujace wskazowki odczytu/zapisu: RWH_WRITE_LIFE_NOT_SET Nie ustawiono zadnej wskazowki. Jest to wartosc domyslna. RWH_WRITE_LIFE_NONE Nie ustawiono wskazowki zapisu z danym plikiem lub i-wezlem. RWH_WRITE_LIFE_SHORT Oczekuje sie, ze dane zapisane do tego i-wezla lub za pomoca tego opisu otwartego pliku, beda istnialy krotko. RWH_WRITE_LIFE_MEDIUM Oczekuje sie, ze dane zapisane do tego i-wezla lub za pomoca tego opisu otwartego pliku, beda istnialy dluzej, niz dane zapisane ze wskazowka RWH_WRITE_LIFE_SHORT. RWH_WRITE_LIFE_LONG Oczekuje sie, ze dane zapisane do tego i-wezla lub za pomoca tego opisu otwartego pliku, beda istnialy dluzej, niz dane zapisane ze wskazowka RWH_WRITE_LIFE_MEDIUM. RWH_WRITE_LIFE_EXTREME Oczekuje sie, ze dane zapisane do tego i-wezla lub za pomoca tego opisu otwartego pliku, beda istnialy dluzej, niz dane zapisane ze wskazowka RWH_WRITE_LIFE_LONG. Wszystkie wskazowki dotyczace zapisu sa jedynie relatywne wzgledem siebie i nie nalezy przypisywac im bezwzglednego znaczenia. WARTOSC ZWRACANA Wartosc zwracana po pomyslnym zakonczeniu funkcji zalezy od operacji: F_DUPFD Nowy deskryptor pliku. F_GETFD Wartosc znacznikow deskryptora pliku. F_GETFL Wartosc znacznikow stanu pliku F_GETLEASE Typ dzierzawy ustanowionej na deskryptorze pliku. F_GETOWN Wartosc wlasciciela deskryptora pliku. F_GETSIG Wartosc sygnalu wyslanego, gdy odczyt lub zapis stana sie mozliwe, lub zero, dla tradycyjnego zachowania SIGIO. F_GETPIPE_SZ F_SETPIPE_SZ Pojemnosc potoku. F_GET_SEALS Mapa bitowa identyfikujaca pieczecie, ktore ustawiono dla i-wezla, do ktorego odnosi sie fd. Wszystkie pozostale operacje Zero. W razie wystapienia bledu zwracane jest -1 i ustawiane errno wskazujac blad. BLEDY EACCES lub EAGAIN Operacja uniemozliwiona przez blokady utrzymywane przez inne procesy. EAGAIN Operacja jest zabroniona, gdyz plik zostal odwzorowany w pamieci 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 zadanej blokady. EBUSY op wynosi F_SETPIPE_SZ, a nowa pojemnosc potoku okreslona w arg jest mniejsza, niz przestrzen bufora aktualnie zajeta do przechowywania danych w potoku. EBUSY op wynosi F_ADD_SEALS, arg zawiera F_SEAL_WRITE i istnieje zapisywalne, dzielone przypisanie pliku, do ktorego odnosi sie fd. EDEADLK Stwierdzono, ze podana operacja F_SETLKW spowodowaloby zakleszczenie blokad. EFAULT lock znajduje sie poza dostepna dla uzytkownika przestrzenia adresowa. EINTR op wynosi F_SETLKW lub F_OFD_SETLKW i operacja zostala przerwana sygnalem; zob. signal(7). EINTR op wynosi F_GETLK, F_SETLK, F_OFD_GETLK lub F_OFD_SETLK, a operacja zostala przerwana przez sygnal, zanim blokada zostala sprawdzona lub ustawiona. Najbardziej prawdopodobne podczas blokowania zdalnego pliku (np. blokowanie przez NFS), ale czasami zdarza sie lokalnie. EINVAL Wartosc podana w op nie jest rozpoznawana przez to jadro. EINVAL op wynosi F_ADD_SEALS, a arg obejmuje nierozpoznany bit pieczeci. EINVAL op wynosi F_ADD_SEALS lub F_GET_SEALS, a system plikow zawierajacy i-wezel, do ktorego odnosi sie fd, nie obsluguje pieczetowania. EINVAL op wynosi F_DUPFD, a arg jest ujemny lub wiekszy od maksymalnej dozwolonej wartosci (wiecej informacji w opisie RLIMIT_NOFILE w podreczniku getrlimit(2)). EINVAL op wynosi F_SETSIG, a arg nie jest dozwolonym numerem sygnalu. 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 osiagnieto juz maksymalna liczbe otwartych deskryptorow plikow na proces. ENOLCK Zbyt wiele otwartych blokad segmentowych, tablica blokad jest pelna lub zawiodl protokol blokowania zdalnego (np. dla blokad przez NFS). ENOTDIR W op podano F_NOTIFY, lecz fd nie odnosi sie do katalogu. EPERM op wynosi F_SETPIPE_SZ i osiagnieto miekki lub sztywny limit potoku; zob. pipe(7). EPERM Probowano wyzerowac znacznik O_APPEND na pliku posiadajacym ustawiony atrybut ,,append-only". EPERM op wynosilo F_ADD_SEALS, lecz fd nie byl otwarty do zapisu albo biezacy zestaw pieczeci juz 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 sa typowo linuksowe (nalezy zdefiniowac makro _GNU_SOURCE aby pozyskac te definicje). F_OFD_SETLK, F_OFD_SETLKW i F_OFD_GETLK sa typowo linuksowe (i konieczne jest zdefiniowanie _GNU_SOURCE do pozyskania ich definicji), lecz trwaja prace nad wlaczeniem ich do nastepnej wersji POSIX.1. F_ADD_SEALS i F_GET_SEALS sa 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 sa okreslone w POSIX.1-2001. F_GETOWN i F_SETOWN sa okreslone w POSIX.1-2001 (do pozyskania ich definicji konieczne jest zdefiniowanie _XOPEN_SOURCE z wartoscia 500 lub wieksza albo _POSIX_C_SOURCE z wartoscia 200809L lub wieksza). F_DUPFD_CLOEXEC jest okreslone w POSIX.1-2008 (do pozyskania jego definicji konieczne jest zdefiniowanie _POSIX_C_SOURCE z wartoscia 200809L lub wieksza albo _XOPEN_SOURCE z wartoscia 700 lub wieksza). UWAGI Bledy zwracane przez dup2(2) sa inne niz zwracane przez F_DUPFD. Blokowanie plikow Pierwotne linuksowe wywolanie systemowego fcntl() nie bylo zaprojektowane do obslugi duzych przesuniec plikow (w strukturze flock). W konsekwencji, Linux 2.4 dodal wywolanie systemowe fcntl64(). Nowsze wywolanie systemowe korzysta z odmiennej struktury do blokowania plikow, flock64 i odpowiadajacych operacji, F_GETLK64, F_SETLK64 i F_SETLKW64. Detale te moga byc jednak zignorowane przez aplikacje uzywajace glibc, poniewaz jej funkcja opakowujaca fcntl() obsluguje nowsze wywolanie systemowe, gdy tylko jest dostepne, w sposob przezroczysty. Blokady rekordow Od Linuksa 2.0, nie ma oddzialywania pomiedzy typami blokad zakladanych przez flock(2) i przez fcntl(). W niektorych systemach struktura struct flock zawiera dodatkowe pola, takie jak np. l_sysid (do identyfikacji komputera, na ktorym utrzymywana jest blokada). Oczywiscie, samo l_pid jest malo przydatne, gdy proces utrzymujacy blokade moze dzialac na innym komputerze; w Linuksie, choc pole to jest obecne na niektorych architekturach (np. MIPS32), to jednak nie jest uzywane. Pierwotne linuksowe wywolanie systemowego fcntl() nie bylo zaprojektowane do obslugi duzych przesuniec plikow (w strukturze flock). W konsekwencji, Linux 2.4 dodal wywolanie systemowe fcntl64(). Nowsze wywolanie systemowe korzysta z odmiennej struktury do blokowania plikow, flock64 i odpowiadajacych operacji, F_GETLK64, F_SETLK64 i F_SETLKW64. Detale te moga byc jednak zignorowane przez aplikacje uzywajace glibc, poniewaz jej funkcja opakowujaca fcntl() obsluguje nowsze wywolanie systemowe, gdy tylko jest dostepne, w sposob przezroczysty. Blokowanie rekordow i NFS Przed Linuksem 3.12, jesli klient NFSv4 utraci kontakt z serwerem na pewien czas (zdefiniowany jako ponad 90 sekund bez zadnej komunikacji), to moze utracic i odzyskac blokade bez uswiadamiania sobie tego faktu (czas, po ktorym przyjmuje sie utrate polaczenia jest znany jako czas dzierzawy NFSv4 (leasetime); na serwerze NFS mozna go sprawdzic w pliku /proc/fs/nfsd/nfsv4leasetime, ktory podaje go w sekundach; domyslna wartoscia w pliku jest 90). Ten scenariusz grozi uszkodzeniem danych, poniewaz inny proces mogl w miedzyczasie posiasc blokade i dokonac operacji wejscia/wyjscia na pliku. Od Linuksa 3.12, jesli klient NFSv4 utraci polaczenie z serwerem, kazda operacja wejscia/wyjscia na pliku, przez proces ktory ,,sadzi", ze utrzymuje blokade zawiedzie, dopoki ten proces nie zamknie i nie otworzy pliku ponownie. Mozna ustawic parametr jadra nfs.recover_lost_locks na 1, aby powrocic do zachowania sprzed wersji 3.12, gdy klient probuje odzyskac zagubione blokady po odzyskaniu polaczenia z serwerem. Ze wzgledu na towarzyszace temu ryzyko uszkodzenia danych, domyslnie parametr ten wynosi 0 (jest wylaczony). USTERKI F_SETFL Nie da sie uzyc F_SETFL do zmiany statusu znacznikow O_DSYNC i O_SYNC. Takie proby zostana po cichu zignorowane. F_GETOWN Ograniczenie konwencji linuksowego wywolania systemowego na niektorych architekturach (przede wszystkim i386) oznacza, ze jesli (ujemny) identyfikator grupy procesu majacy byc zwrocony przez F_GETOWN znajduje sie w przedziale od -1 do -4095, to zwracana wartosc jest przez glibc nieprawidlowo interpretowana jako blad w wywolaniu systemowym; to jest zwrocona przez fcntl() wartosc bedzie wynosila -1, a errno bedzie zawierac (dodatni) identyfikator grupy procesu. Typowo linuksowa operacja F_GETOWN_EX unika tego problemu. Od glibc 2.11, glibc czyni problem jadra F_GETOWN niewidzialnym, przez zaimplementowanie F_GETOWN za pomoca F_GETOWN_EX. F_SETOWN W Linuksie 2.4 i wczesniejszych istnieje blad, ktory moze sie ujawnic, gdy proces nieuprzywilejowany uzywa F_SETOWN do podania wlasciciela deskryptora pliku gniazda, bedace procesem (grupa) inna niz wywolujacy. W tym przypadku fcntl() moze zwrocic -1 z errno ustawionym na EPERM nawet wowczas, gdy wlasciciel procesu (grupy) byl tym, do ktorego wywolujacy ma prawo wysylania sygnalow. Pomimo zwracania bledu, wlasnosc deskryptora pliku jest ustawiana, a sygnaly beda wysylane do wlasciciela. Wykrywanie zakleszczen Algorytm wykrywania zakleszczen uzywany przez jadro przy przetwarzaniu zadan F_SETLKW moze skutkowac wykryciami zarowno falszywie negatywnymi (niewykryciem zakleszczen, pozostawiajac zestaw zakleszczonych procesow stale zablokowanymi), jak i falszywie pozytywnymi (blad EDEADLK, gdy zakleszczenie nie wystepuje). Przykladowo, jadro ogranicza glebokosc poszukiwania zaleznosci blokad do 10 krokow co oznacza, ze lancuch kolistych zakleszczen wiekszy od tego rozmiaru nie zostanie wykryty. Dodatkowo, jadro moze nieprawidlowo wskazywac zakleszczenie, gdy dwa lub wiecej procesow utworzonych za pomoca znacznika CLONE_FILES z clone(2), wygladaja (dla jadra) na bedace w konflikcie. Blokowanie obowiazujace (przymusowe) Linuksowa implementacja blokowania obowiazujacego (przymusowego) jest podatna na sytuacje wyscigu, co czyni ja nierzetelna: wywolanie write(2), ktore nachodzi na blokade moze zmodyfikowac dane po uzyskaniu blokady, wywolanie read(2) ktore nachodzi na blokade moze wykryc zmiane danych, dokonana jedynie po uzyskaniu blokady zapisu. Podobny wyscig istnieje pomiedzy blokadami obowiazujacymi a mmap(2). Z tego powodu nie nalezy polegac na blokowaniu obowiazujacym. ZOBACZ TAKZE 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/ zrodel jadra Linux (w starszych jadrach pliki te znajduja sie bezposrednio w katalogu Documentation/, a plik mandatory-locking.txt ma nazwe mandatory.txt) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Przemek Borys , Andrzej Krzysztofowicz i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.8 2 maja 2024 r. fcntl(2)