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

NAZWA
open, creat - otwiera i ewentualnie tworzy plik
BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)
SKŁADNIA
#include <fcntl.h>
int open(const char *pathname, int flags, ...
/* mode_t mode */ );
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags, ...
/* mode_t mode */ );
/* Udokumentowane oddzielnie, w openat2(2):
*/
int openat2(int dirfd, const char *pathname,
const struct open_how *how, size_t size);
Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):
openat():
Od glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Przed glibc 2.10:
_ATFILE_SOURCE
OPIS
Wywołanie systemowe open() otwiera plik określony ścieżką pathname. Jeśli podany plik nie istnieje, może
być opcjonalnie (jeśli we flags podano O_CREAT) utworzony przez open().
Wartością zwracaną przez open() jest deskryptor pliku: niewielka, całkowita liczba nieujemna, będąca
indeksem wpisu w tablicy otwartych deskryptorów plików procesu. Deskryptor pliku jest używany w kolejnych
wywołaniach systemowych (read(2), write(2), lseek(2), fcntl(2) itp.), w celu odniesienia się do otwartego
pliku. Deskryptor pliku zwracany przez pomyślne wywołanie będzie najniższym numerem deskryptora pliku,
który nie jest aktualnie otwarty przez proces.
Domyślnie, nowy deskryptor pliku jest ustawiany jako pozostający otwarty po wykonaniu przez execve(2)
(tj. znacznik deskryptora pliku FD_CLOEXEC opisany w fcntl(2) jest początkowo wyłączony); można użyć
opisanego poniżej znacznika O_CLOEXEC aby zmienić to zachowanie. Przesunięcie pliku jest ustawiane na
początek pliku (zob. lseek(2)).
Wywołanie open() tworzy nowy opis otwartego pliku, wpis w systemowej tablicy otwartych plików. Opis
otwartego pliku zawiera przesunięcie pliku i znaczniki statusu pliku (zob. niżej). Deskryptor pliku
odnosi się do opisu otwartego pliku i na to odniesienie nie ma wpływu późniejsze usunięcie ścieżki
pathname lub jej modyfikacja, w celu wskazania innego pliku. Więcej informacji o opisach otwartego pliku
zawarto w rozdziale UWAGI.
Argument flags musi zawierać jeden z następujących trybów dostępu: O_RDONLY, O_WRONLY lub O_RDWR.
Stanowią one, odpowiednio, żądania otwarcia tylko do odczytu, tylko do zapisu, lub do odczytu i zapisu.
Ponadto, we flags może zsumować bitowo (OR) zero lub więcej znaczników tworzenia pliku i znaczników
statusu pliku. Znaczniki tworzenia pliku to: O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY,
O_NOFOLLOW, O_TMPFILE i O_TRUNC. Znaczniki statusu pliku to wszystkie pozostałe znaczniki, wypisane
poniżej. Rozróżnieniem pomiędzy tymi dwoma grupami znaczników jest fakt, że znaczniki tworzenia pliku
wpływają na zachowanie samej operacji otwarcia, natomiast znaczniki statusu pliku wpływają na zachowanie
kolejnych operacji wejścia/wyjścia. Znaczniki statusu pliku można pobrać i (w niektórych przypadkach)
zmodyfikować; więcej szczegółów w podręczniku fcntl(2).
Oto pełna lista znaczników tworzenia pliku i znaczników statusu pliku:
O_APPEND
Plik jest otwierany w trybie dopisywania. Przed każdą operacją write(2), przesunięcie pliku jest
ustawiane na koniec pliku, jak z lseek(2). Modyfikacja przesunięcia pliku i operacja zapisu jest
przeprowadzana jako jeden, niepodzielny krok.
O_APPEND może prowadzić do uszkodzenia plików na systemach plików NFS, gdy więcej niż jeden proces
naraz dopisuje dane do pliku. Jest to związane z faktem, że NFS nie obsługuje dopisywania do
pliku, więc jądro klienta musi to zasymulować, co nie może zostać wykonane bez wyścigu.
O_ASYNC
Włącza wejście/wyjście sterowane sygnałem: generuje sygnał (domyślnie SIGIO, ale można go zmienić
za pomocą fcntl(2)), gdy wejście lub wyjście poprzez ten deskryptor pliku staje się możliwe. Ta
funkcja jest dostępna jedynie dla terminali, pseudoterminali, gniazd i (od Linuksa 2.6) potoków
oraz FIFO. Więcej szczegółów można znaleźć w podręczniku fcntl(2). Zob. też USTERKI poniżej.
O_CLOEXEC (od Linuksa 2.6.23)
Włącza znacznik zamknięcia-przy-wykonaniu dla nowego deskryptora pliku. Podanie tego znacznika
umożliwia uniknięcie przez program wykonywania dodatkowych operacji F_SETFD fcntl(2) w celu
ustawienia znacznika FD_CLOEXEC.
Proszę zauważyć, że korzystanie z tego znacznika jest niezbędne w niektórych programach
wielowątkowych, ponieważ oddzielna operacja F_SETFD fcntl(2), ustawiająca znacznik FD_CLOEXEC, nie
zapobiega wystąpieniu sytuacji wyścigu, gdy jeden wątek otwiera deskryptor pliku, próbując ustawić
swój znacznik zamknięcia-przy-wykonaniu za pomocą fcntl(2), a w tym samym czasie inny wątek
dokonuje fork(2) oraz execve(2). W zależności od kolejności wykonania, wyścig ten może spowodować
nieoczekiwany wyciek deskryptora pliku zwróconego przez open(), do programu wykonywanego przez
proces potomny utworzony przez fork(2) (jest to typ wyścigu, który jest teoretycznie możliwy dla
każdego wywołania systemowego tworzącego deskryptor pliku, który powinien otrzymać znacznik
zamknięcia-przy-wykonaniu, dlatego różne inne linuksowe wywołania systemowe udostępniają
równoważnik znacznika O_CLOEXEC, aby poradzić sobie z tym problemem).
O_CREAT
Jeśli pathname nie istnieje, tworzy ją jako zwykły plik.
Właściciel (identyfikator użytkownika) nowego pliku jest ustawiany na efektywny identyfikator
użytkownika procesu.
Własność grupy (identyfikator grupy) nowego pliku jest ustawiana na efektywny identyfikator grupy
procesu (zachowanie Systemu V) lub na identyfikator grupy katalogu nadrzędnego (zachowanie BSD). W
Linuksie, wybór typu zachowania zależy od ustawienia bitu trybu set-group-ID w katalogu
nadrzędnym: jeśli bit ten jest ustawiony, wybierane jest zachowanie BSD; w przeciwnym razie,
stosowane jest zachowanie Systemu V. W przypadku niektórych systemów plików, zachowanie to zależy
również od opcji montowania bsdgroups i sysvgroups, które opisano w podręczniku mount(8).
Argument mode określa bity trybu pliku, jakie mają być zastosowane do nowo tworzonego pliku. Jeśli
nie poda się O_CREAT ani O_TMPFILE we flags, to mode jest ignorowane (można je zatem podać jako 0
lub po prostu pominąć). Argument mode musi być określony, jeśli we flags podano O_CREAT lub
O_TMPFILE; jeśli się go nie poda, jako tryb pliku zostaną użyte jakieś losowe bajty ze stosu.
Efektywny tryb jest modyfikowany przez umask procesu, w zwykły sposób: pod nieobecność domyślnych
list kontroli dostępu (ACL), trybem tworzonego pliku jest (mode & ~umask).
Proszę zauważyć, że mode stosuje się tylko do kolejnych dostępów do nowo tworzonego pliku;
wywołanie open(), które tworzy plik tylko do odczytu, może zwrócić również deskryptor pliku do
odczytu i do zapisu.
Dla parametru mode udostępniono następujące stałe symboliczne:
S_IRWXU 00700 użytkownik (właściciel pliku) ma prawa odczytu, zapisu i uruchamiania.
S_IRUSR 00400 użytkownik ma prawa odczytu.
S_IWUSR 00200 użytkownik ma prawa zapisu.
S_IXUSR 00100 użytkownik ma prawa uruchamiania.
S_IRWXG 00070 grupa ma prawa odczytu, zapisu i uruchamiania.
S_IRGRP 00040 grupa ma prawa odczytu.
S_IWGRP 00020 grupa ma prawa zapisu.
S_IXGRP 00010 grupa ma prawa uruchamiania.
S_IRWXO 00007 inni mają prawa odczytu, zapisu i uruchamiania.
S_IROTH 00004 inni mają prawa odczytu.
S_IWOTH 00002 inni mają prawa zapisu.
S_IXOTH 00001 inni mają prawa uruchamiania.
Zgodnie z POSIX, wpływ ustawienia innych bitów w mode jest nieokreślony. W Linuksie, honorowane
jest również ustawienie następujących bitów w mode:
S_ISUID 0004000 bit set-user-ID
S_ISGID 0002000 bit set-group-ID (zob. inode(7)).
S_ISVTX 0001000 bit lepkości (zob. inode(7)).
O_DIRECT (od Linuksa 2.4.10)
Powoduje próbę zminimalizowania efektów związanych z buforowaniem wejścia/wyjścia do i z tego
pliku. Na ogół spowoduje to zmniejszenie wydajności, ale jest to przydatne w specyficznych
sytuacjach, na przykład gdy aplikacje buforują we własnym zakresie. Wejście/wyjście dla pliku
odbywa się wówczas bezpośrednio z/do buforów w przestrzeni użytkownika. Sam znacznik O_DIRECT
stara się dokonywać transferu synchronicznie, ale nie daje gwarancji znacznika O_SYNC, że dane i
wymagane metadane są transferowane. Aby zagwarantować synchroniczne wejście/wyjście, oprócz
O_DIRECT konieczne jest użycie również O_SYNC. Więcej informacji w rozdziale UWAGI poniżej.
Semantycznie podobny (lecz przestarzały) interfejs dla urządzeń blokowych opisano w raw(8).
O_DIRECTORY
Jeśli pathname nie jest katalogiem, spowoduje niepowodzenie otwarcia. Ten znacznik dodano w
Linuksie 2.1.126, aby uniknąć problemów blokowania usług (DoS), gdy opendir(3) jest wywołane dla
FIFO lub dla urządzenia taśmowego.
O_DSYNC
Operacje zapisu pliku zakończą się zgodnie z wymaganiem kompletności zsynchronizowanego
wejścia/wyjścia danych w sposób gwarantujący spójność.
W chwili powrotu write(2) (i podobnego), dane wyjściowe zostały już przeniesione na właściwe
urządzenie, razem ze wszystkimi metadanymi pliku, które są konieczne do pobrania tych danych (tzn.
jest to równoważne jak gdyby po każdym write(2) wywoływać fdatasync(2)). Proszę zapoznać się z
UWAGAMI poniżej.
O_EXCL Zapewnia, że to wywołanie utworzy plik: jeśli znacznik poda się razem z O_CREAT, a ścieżka
pathname już istnieje, to open() zawiedzie z błędem EEXIST.
Po podaniu obu tych znaczników, nie podąża się za dowiązaniami symbolicznymi: jeśli pathname jest
dowiązaniem symbolicznym, to open() zawiedzie niezależnie od tego, na co wskazuje to dowiązanie
symboliczne.
Co do zasady, zachowanie O_EXCL jest niezdefiniowane, jeśli użyje się go bez O_CREAT. Jest jeden
wyjątek: w Linuksie 2.6 i późniejszych, O_EXCL można użyć bez O_CREAT jeśli pathname odnosi się do
urządzenia blokowego. Jeśli urządzenie blokowe jest w użyciu przez system (np. jest zamontowane),
to open() zawiedzie z błędem EBUSY.
W systemie plików NFS O_EXCL jest obsługiwane tylko w NFSv3 lub późniejszym na jądrze 2.6 lub
późniejszym. W środowiskach NFS, gdzie nie zapewniono obsługi O_EXCL, programy które polegają na
nim, w celu dokonywania zadań blokowania, będą prowadziły do wyścigu. Przenośne programy, które
chcą przeprowadzać niepodzielne blokowanie pliku za pomocą pliku-blokady i muszą unikać polegania
na obsłudze O_EXCL w NFS, mogą tworzyć unikalny plik na tym samym systemie plików (np.
wykorzystując nazwę stacji i PID) i używać link(2) do utworzenia dowiązania do pliku-blokady.
Jeśli link(2) zwróci 0, to utworzenie blokady się powiodło. W przeciwnym razie, należy użyć
stat(2) na unikalnym pliku, aby sprawdzić, czy ilość jego dowiązań wzrosła do 2. W takiej sytuacji
utworzenie blokady również się powiodło.
O_LARGEFILE
(LFS) Pozwala na otwarcie plików, których rozmiarów nie można przedstawić w off_t (lecz można w
off64_t). Konieczne jest zdefiniowanie makra _LARGEFILE64_SOURCE (przed włączeniem jakichkolwiek
plików nagłówkowych) aby uzyskać jego definicję. Ustawienie makra sprawdzania cech
_FILE_OFFSET_BITS na 64 (zamiast na O_LARGEFILE) jest preferowaną metodą uzyskiwania dostępu do
dużych plików w systemach 32-bitowych (zob. feature_test_macros(7)).
O_NOATIME (od Linuksa 2.6.8)
Nie aktualizuje czasu ostatniego dostępu do pliku (st_atime w i-węźle) gdy plik jest odczytywany
(read(2)).
Znacznik ten można użyć tylko, jeśli spełniony zostanie jeden z poniższych warunków:
• Efektywny UID procesu jest zgodny z UID-em właściciela pliku.
• Proces wywołujący ma przywilej CAP_FOWNER (ang. capability) w swojej przestrzeni nazw
użytkownika, a UID właściciela pliku ma przypisanie do tej przestrzeni nazw.
Znacznik ten jest przeznaczony dla programów indeksujących lub tworzących kopie zapasowe, gdzie
pozwala na znaczną redukcję aktywności dysku. Znacznik ten może nie działać we wszystkich
systemach plików. Jednym z przykładów jest NFS, gdzie to serwer zarządza czasami dostępu.
O_NOCTTY
Jeśli pathname odnosi się do urządzenia terminalowego — zob. tty(4) — to nie stanie się terminalem
sterującym procesu, nawet jeśli proces takiego nie ma.
O_NOFOLLOW
Jeśli końcowa składowa (basename) ścieżki pathname jest dowiązaniem symbolicznym, to otwarcie
zawiedzie z błędem ELOOP. Dowiązania symboliczne wcześniejszych składowych ścieżki wciąż zostaną
rozwinięte (proszę zauważyć, że błąd ELOOP, który może się zdarzyć w tym przypadku, jest
nierozróżnialny od sytuacji, gdy otwarcie zawiedzie, z powodu zbyt wielu dowiązań symbolicznych,
które wystąpiły przy rozwiązywaniu wcześniejszych składowych ścieżki).
Znacznik ten jest rozszerzeniem FreeBSD, który został dodany w Linuksie 2.1.126 i został później
wprowadzony jako standard w normie POSIX.1-2008.
Zob. też O_PATH poniżej.
O_NONBLOCK lub O_NDELAY
Plik jest otwierany w trybie nieblokującym, o ile to możliwe. Ani open() ani kolejne operacje
wejścia/wyjścia, na zwróconym przez to wywołanie deskryptorze, nie spowodują blokowania procesu
wywołującego.
Proszę zauważyć, że ustawienie tego znacznika nie ma wpływu na działanie poll(2), select(2),
epoll(7) i podobnych, ponieważ interfejsy te jedynie informują wywołującego o tym, gdy deskryptor
pliku jest „gotowy” co oznacza, że operacja wejścia/wyjścia na deskryptorze pliku ze znacznikiem
O_NONBLOCK zdecydowanie nie prowadziłaby do zablokowania.
Proszę zauważyć, że znacznik ten nie ma wpływu na zwykłe pliki i urządzenia blokowe tzn. operacja
wejścia/wyjścia będzie (chwilowo) blokować, gdy wymagana jest aktywność urządzenia, niezależnie od
ustawienia O_NONBLOCK. Ponieważ takie zachowanie O_NONBLOCK może w przyszłości być
zaimplementowane, aplikacje nie powinny zależeć od zachowania blokowania, przy podawaniu tego
znacznika w przypadku zwykłych plików i urządzeń blokowych.
Szczegóły dotyczące obsługi FIFO (nazwanych potoków) można znaleźć w podręczniku fifo(7). Opis
wpływu znacznika O_NONBLOCK, w połączeniu z blokadami obowiązującymi (przymusowymi) oraz z
dzierżawami pliku, znajduje się w podręczniku fcntl(2).
O_PATH (od Linuksa 2.6.39)
Pozyskuje deskryptor pliku, którego można użyć w dwóch celach: do wskazania położenia w drzewie
systemu plików i do przeprowadzenia operacji, które działają na poziomie samego deskryptora pliku.
Sam plik nie jest otwierany, dlatego inne operacje plikowe (np. read(2), write(2), fchmod(2),
fchown(2), fgetxattr(2), ioctl(2), mmap(2)) zawiodą z błędem EBADF.
Na wynikowym deskryptorze pliku można wykonać następujące operacje:
• close(2).
• fchdir(2), jeśli deskryptor pliku odnosi się do katalogu (od Linuksa 3.5).
• fstat(2) (od Linuksa 3.6).
• fstatfs(2) (od Linuksa 3.12).
• Zduplikowanie deskryptora pliku (dup(2), F_DUPFD z fcntl(2), itp).
• Uzyskanie i ustawienie znaczników deskryptora pliku (F_GETFD i F_SETFD z fcntl(2)).
• Pobranie znaczników statusu otwartego pliku za pomocą operacji F_GETFL z fcntl(2): zwrócone
znaczniki będą obejmowały również bit O_PATH.
• Przekazanie deskryptora pliku jako argumentu dirfd do openat() i innych wywołań systemowych
„*at()”. Obejmuje to również linkat(2) z AT_EMPTY_PATH (lub za pomocą procfs wykorzystując
AT_SYMLINK_FOLLOW) nawet, gdy plik nie jest katalogiem.
• Przekazanie deskryptora pliku do innego procesu za pomocą gniazda domeny Uniksa (zob.
SCM_RIGHTS w podręczniku unix(7)).
Gdy O_PATH poda się we flags, to bity znaczników inne niż O_CLOEXEC, O_DIRECTORY i O_NOFOLLOW są
ignorowane.
Otwarcie pliku lub katalogu ze znacznikiem O_PATH nie wymaga uprawnień do samego obiektu (lecz
wymaga uprawnienia wykonania (przeszukiwania) na katalogach w składowej ścieżki). W zależności od
kolejnej operacji, może być wykonane sprawdzenie odpowiednich uprawnień pliku (np. fchdir(2)
wymaga uprawnienia wykonania (przeszukania) na katalogu, do którego odnosi się jego argument z
deskryptorem pliku). Odmiennie, przy uzyskiwaniu odniesienia do obiektu systemu plików za pomocą
znacznika O_RDONLY, wymagane jest posiadanie przez wywołującego uprawnienia odczytu, nawet gdy
kolejna operacja (np. fchdir(2), fstat(2)) nie wymaga uprawnienia odczytu do obiektu.
Jeśli pathname jest dowiązaniem symbolicznym i podano również znacznik O_NOFOLLOW, to wywołanie
zwróci deskryptor pliku odnoszący się do dowiązania symbolicznego. Ten deskryptor pliku może
służyć jako argument dirfd w wywołaniach do fchownat(2), fstatat(2), linkat(2) i readlinkat(2) z
pustą ścieżką, aby wywołania działały na samym dowiązaniu symbolicznym.
Jeśli pathname odnosi się do punktu automatycznego montowania, który nie został jeszcze wyzwolony,
tak więc nie zamontowano w nim innego systemu plików, to wywołanie zwróci deskryptor pliku
odnoszący się do katalogu automatycznego montowania, bez wyzwalania montowania. Można następnie
użyć fstatfs(2), aby sprawdzić, czy jest to faktycznie niewyzwolony punkt automatycznego
montowania (.f_type == AUTOFS_SUPER_MAGIC).
Można użyć O_PATH w przypadku zwykłych plików, aby uzyskać funkcjonalność równoważną O_EXEC z
POSIX.1. Pozwala to na otwarcie pliku, do którego posiada się uprawnienie wykonywania, ale nie
posiada się uprawnienia odczytu, a następnie wykonanie pliku, za pomocą kroków podobnych do
poniższych:
char buf[PATH_MAX];
fd = open("jakiś_program", O_PATH);
snprintf(buf, PATH_MAX, "/proc/self/fd/%d", fd);
execl(buf, "jakiś_program", (char *) NULL);
Deskryptor pliku O_PATH może być również przekazany jako argument fexecve(3).
O_SYNC Operacje zapisu na pliku zakończą się zgodnie z wymaganiem kompletności zsynchronizowanego
wejścia/wyjścia pliku w sposób gwarantujący spójność (odmiennie od zakończenia zgodnie z
wymaganiem kompletności zsynchronizowanego wejścia/wyjścia danych, udostępnianego przez O_DSYNC).
W chwili powrotu write(2) (i podobnego), dane wyjściowe i powiązane metadane pliku zostały już
przeniesione na właściwe urządzenie (tzn. jest to równoważne jak gdyby po każdym write(2)
wywoływać fsync(2)). Proszę zapoznać się z UWAGAMI poniżej.
O_TMPFILE (od Linuksa 3.11)
Tworzy nienazwany, zwykły plik tymczasowy. Argument pathname określa katalog, w katalogu tym, w
systemie plików zostanie utworzony nienazwany i-węzeł. Wszystko, co zostanie zapisane do
wynikowego pliku, ulegnie utracie po zamknięciu ostatniego deskryptora pliku chyba, że plik
otrzyma nazwę.
Ze znacznikiem O_TMPFILE należy użyć O_RDWR lub O_WRONLY i, opcjonalnie, O_EXCL. Jeśli nie poda
się O_EXCL, to można skorzystać z linkat(2) do utworzenia dowiązania do systemu plików, czyniąc
plik stałym, za pomocą kodu podobnego do poniższego:
char path[PATH_MAX];
fd = open("/ścieżka/do/katalogu", O_TMPFILE | O_RDWR,
S_IRUSR | S_IWUSR);
/* Wejście/wyjście na 'fd'... */
linkat(fd, "", AT_FDCWD, "/ścieżka/do/pliku", AT_EMPTY_PATH);
/* Jeśli wywołujący nie ma przywileju CAP_DAC_READ_SEARCH
(potrzebnego do użycia AT_EMPTY_PATH z linkat(2)),
i system plików proc(5) jest zamontowany, to powyższe
wywołanie linkat(2) można zastąpić przez:
snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
linkat(AT_FDCWD, path, AT_FDCWD, "/ścieżka/do/pliku",
AT_SYMLINK_FOLLOW);
*/
W tym przypadku argument mode open() określa tryb uprawnień pliku, podobnie jak przy O_CREAT.
Podanie O_EXCL w połączeniu z O_TMPFILE zapobiega możliwości utworzenia dowiązania do systemu
plików w powyższy sposób (proszę zauważyć, że znaczenie O_EXCL w tym przypadku różni się od
znaczenia O_EXCL w pozostałych przypadkach).
Istnieją dwa główne zastosowania O_TMPFILE:
• Usprawniona funkcjonalność tmpfile(3): tworzenie plików tymczasowych bez ryzyka wystąpienia
wyścigu, które: (1) są automatycznie usuwane po zamknięciu; (2) nie da się do nich dostać za
pomocą żadnej ścieżki; (3) nie są przedmiotem ataków na dowiązania symboliczne oraz (4) nie
wymagają wymyślania przez wywołującego unikatowych nazw.
• Tworzenie plików początkowo niewidocznych, które są następnie wypełniane danymi i dostosowywane
w celu posiadania właściwych atrybutów systemu plików (fchown(2), fchmod(2), fsetxattr(2) itp.)
przed niepodzielnym utworzeniem dowiązania do systemu plików, w stanie już w pełni
ukształtowanym (za pomocą opisanego wyżej linkat(2)).
O_TMPFILE wymaga obsługi w podległym systemie plików; jedynie podzbiór linuksowych systemów plików
ją zapewnia. W pierwotnej implementacji, obsługę zapewniały system plików ext2, ext3, ext4, UDF,
Minix i tmpfs. Następnie dodano obsługę kolejnych systemów plików: XFS (Linux 3.15); Btrfs (Linux
3.16); F2FS (Linux 3.16) oraz ubifs (Linux 4.9)
O_TRUNC
Jeśli plik już istnieje, jest zwykłym plikiem i tryb dostępu pozwala na zapis (tzn. jest to O_RDWR
lub O_WRONLY), to plik ten zostanie obcięty do zerowej długości. Jeśli plik to FIFO lub urządzenie
terminalowe, to znacznik O_TRUNC jest ignorowany. W pozostałych przypadkach efekt użycia znacznika
O_TRUNC jest nieokreślony.
creat()
Wywołanie creat() jest równoważne wywołaniu open() z argumentem flags ustawionym na
O_CREAT|O_WRONLY|O_TRUNC.
openat()
Wywołanie systemowe openat() operuje w dokładnie taki sam sposób jak open(), z wyjątkiem różnic opisanych
tutaj.
Argument dirfd jest używany w połączeniu z argumentem pathname, w następujący sposób:
• Jeśli ścieżka podana w pathname jest bezwzględna, to dirfd jest ignorowane.
• Jeśli ścieżka podana w pathname jest względna, a dirfd ma wartość specjalną AT_FDCWD, to pathname jest
interpretowana względem bieżącego katalogu roboczego procesu wywołującego (jak open()).
• Jeśli ścieżka podana w pathname jest względna, to jest interpretowana względem katalogu, do którego
odnosi się deskryptor pliku dirfd (zamiast w odniesieniu do bieżącego katalogu roboczego procesu
wywołującego, jak czyni to open() w stosunku do ścieżek względnych). W tym przypadku, dirfd musi być
katalogiem, który był otwarty do odczytu (O_RDONLY) lub za pomocą znacznika O_PATH.
Jeśli ścieżka podana w pathname jest względna, a dirfd nie jest prawidłowym deskryptorem pliku, to
wystąpi błąd (EBADF; można zatem posłużyć się tym mechanizmem do upewnienia się, że ścieżka pathname jest
bezwzględna, podając w dirfd nieprawidłowy numer deskryptora).
openat2(2)
Wywołanie systemowe openat2(2) jest rozszerzeniem openat() i udostępnia nadzbiór funkcji wobec openat().
Jest udokumentowane oddzielnie, w podręczniku openat2(2).
WARTOŚĆ ZWRACANA
W przypadku powodzenia, open(), openat() i creat() zwracają nowy deskryptor pliku (liczbę nieujemną). W
razie wystąpienia błędu zwracane jest -1 i ustawiane errno wskazując błąd.
BŁĘDY
open(), openat() i creat() mogą zawieść z powodu następujących błędów:
EACCES Żądany dostęp do pliku nie jest dozwolony, odmówiono uprawnienia przeszukiwania dla jednego z
katalogów składowych ścieżki pathname, plik jeszcze nie istnieje i nie dozwolono na dostęp do
zapisu do katalogu nadrzędnego (zob. też path_resolution(7)).
EACCES Gdy podano O_CREAT, włączona jest kontrolka systemowa sysctl protected_fifos lub
protected_regular, plik już istnieje i jest FIFO lub zwykłym plikiem, właścicielem pliku nie jest
ani bieżący użytkownik, ani właściciel katalogu nadrzędnego oraz katalog nadrzędny jest
zapisywalny zarówno dla wszystkich lub dla grupy, jak i ma ustawiony bit lepkości. Więcej
szczegółów w opisach /proc/sys/fs/protected_fifos i /proc/sys/fs/protected_regular w podręczniku
proc_sys_fs(5).
EBADF (openat()) pathname jest względne, lecz dirfd nie wynosi ani AT_FDCWD, ani nie jest prawidłowym
deskryptorem pliku.
EBUSY We flags podano O_EXCL, a ścieżka pathname odnosi się do urządzenia blokowego, które jest w użyciu
przez system (np. jest zamontowane).
EDQUOT Podano O_CREAT, plik nie istnieje, a przydział bloków dyskowych lub i-węzłów dla użytkownika w
systemie plików wyczerpał się.
EEXIST pathname już istnieje, a użyto O_CREAT i O_EXCL.
EFAULT pathname wskazuje poza dostępną dla użytkownika przestrzeń adresową.
EFBIG Zob. EOVERFLOW.
EINTR Wywołanie zostało przerwane przez procedurę obsługi sygnału, w trakcie zablokowania w oczekiwaniu
na ukończenie otwarcia na powolnym (np. FIFO; zob. fifo(7)) urządzeniu; zob. signal(7).
EINVAL System plików nie obsługuje znacznika O_DIRECT. Więcej informacji w UWAGACH.
EINVAL Nieprawidłowa wartość we flags.
EINVAL We flags podano O_TMPFILE, lecz nie podano O_WRONLY, ani O_RDWR.
EINVAL We flags podano O_CREAT, lecz ostatnia składowa („basename”) ścieżki pathname nowego pliku jest
nieprawidłowa (np. zawiera znaki, które nie są dozwolone w danym systemie plików).
EINVAL Ostatnia składowa („basename”) ścieżki pathname jest nieprawidłowa (np. zawiera znaki, które nie
są dozwolone w danym systemie plików).
EISDIR pathname odnosi się do katalogu, a żądany był dostęp z prawem zapisu (tzn. ustawione było O_WRONLY
lub O_RDWR).
EISDIR pathname odnosi się do istniejącego katalogu, we flags podano O_TMPFILE i jeden z: O_WRONLY lub
O_RDWR, lecz ta wersja jądra nie zapewnia funkcjonalności O_TMPFILE.
ELOOP Podczas rozwiązywania pathname napotkano zbyt wiele dowiązań symbolicznych.
ELOOP pathname była dowiązaniem symbolicznym, a we flags podano O_NOFOLLOW, lecz nie podano O_PATH.
EMFILE Osiągnięto limit liczby otwartych deskryptorów pliku na proces (zob. opis RLIMIT_NOFILE w
podręczniku getrlimit(2)).
ENAMETOOLONG
pathname było zbyt długie.
ENFILE Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.
ENODEV pathname odnosi się do pliku urządzenia specjalnego, a odpowiadające mu urządzenie nie istnieje
(jest to błąd w jądrze Linux; w takiej sytuacji powinno być zwracane ENXIO).
ENOENT Nie ustawiono O_CREAT, a nazwany plik nie istnieje.
ENOENT Składowa pathname, która powinna być katalogiem nie istnieje lub jest wiszącym dowiązaniem
symbolicznym.
ENOENT pathname odnosi się do nieistniejącego katalogu, we flags podano O_TMPFILE i jeden z: O_WRONLY lub
O_RDWR, lecz ta wersja jądra nie zapewnia funkcjonalności O_TMPFILE.
ENOMEM Nazwany plik jest FIFO, lecz nie można przydzielić pamięci dla bufora FIFO, ponieważ osiągnięto
bezwzględny limit pamięci przydzielanej potokom na użytkownika, a wywołujący nie jest
uprzywilejowany; zob. pipe(7).
ENOMEM Brak pamięci jądra.
ENOSPC Gdy pathname miało być utworzone, okazało się, że na urządzeniu na którym miało się znajdować brak
miejsca na nowy plik.
ENOTDIR
Składowa użyta w pathname jako katalog w rzeczywistości nie jest katalogiem lub podano
O_DIRECTORY, a pathname nie było katalogiem.
ENOTDIR
(openat()) pathname jest ścieżką względną a dirfd jest deskryptorem pliku odnoszącym się do pliku
zamiast do katalogu.
ENXIO Podano O_NONBLOCK | O_WRONLY, plik o zadanej nazwie stanowi FIFO i nie jest ono otwarte dla
żadnego procesu do odczytu.
ENXIO Plik jest specjalnym plikiem urządzenia, a odpowiadające mu urządzenie nie istnieje.
ENXIO Plik jest gniazdem domeny Uniksa.
EOPNOTSUPP
System plików zawierający pathname nie obsługuje O_TMPFILE.
EOVERFLOW
Ścieżka pathname odnosi się do zwykłego pliku, który jest zbyt duży, aby móc go otworzyć. Zwykle
jest to sytuacja, w której aplikacja skompilowana na platformie 32-bitowej bez
-D_FILE_OFFSET_BITS=64 próbuje otworzyć plik o rozmiarze ponad (1<<31)-1 bajtów; zob. też
O_LARGEFILE powyżej. Jest to kod błędu wynikający z POSIX.1; przed Linuksem 2.6.24, Linux w takiej
sytuacji generował błąd EFBIG.
EPERM Podano znacznik O_NOATIME, ale efektywny identyfikator użytkownika wywołującego nie równał się
właścicielowi pliku, a wywołujący nie był uprzywilejowany.
EPERM Operacja zablokowana, z powodu zapieczętowania pliku (ang. file seal); zob. fcntl(2).
EROFS pathname odnosi się do pliku na systemie plików tylko do odczytu, a żądano otwarcia w trybie do
zapisu.
ETXTBSY
pathname odnosi się do wykonywalnego obrazu, który obecnie jest wykonywany, a zażądano dostępu do
zapisu.
ETXTBSY
pathname odnosi się do pliku, używanego obecnie jako pliku wymiany, a podano znacznik O_TRUNC.
ETXTBSY
pathname odnosi się do pliku aktualnie odczytywanego przez jądro (np. do załadowania
modułu/oprogramowania układowego), a zażądano dostępu do zapisu.
EWOULDBLOCK
Podano znacznik O_NONBLOCK, a na pliku utrzymywana jest niezgodna dzierżawa (zob. fcntl(2)).
WERSJE
(Niezdefiniowany) wynik O_RDONLY | O_TRUNC różni się w zależności od implementacji. W wielu systemach
plik jest faktycznie przycinany.
Synchronizowane wejście/wyjście
Opcja POSIX.1-2008 „synchronized I/O” określa różne warianty synchronizowanego wejścia/wyjścia i podaje
znaczniki O_SYNC, O_DSYNC i O_RSYNC open() jako przeznaczone do kontrolowania oczekiwanego zachowania.
Niezależnie od tego, czy dana implementacja obsługuje tę opcję, obowiązkowa jest obsługa co najmniej
O_SYNC w przypadku zwykłych plików.
Linux implementuje O_SYNC i O_DSYNC, lecz nie O_RSYNC. Poniekąd niewłaściwie, glibc definiuje O_RSYNC
jako mające tę samą wartość co O_SYNC (O_RSYNC jest zdefiniowane w linuksowym pliku nagłówkowym
<asm/fcntl.h> na architekturze HP PA-RISC, lecz nie jest używane).
O_SYNC zapewnia kompletność zsynchronizowanego wejścia/wyjścia pliku w sposób gwarantujący spójność tzn.
operacje zapisu przenoszą dane i wszystkie powiązane metadane na przedmiotowe urządzenie. O_DSYNC
zapewnia kompletność zsynchronizowanego wejścia/wyjścia danych w sposób gwarantujący spójność tzn.
operacje zapisu przenoszą dane na przedmiotowe urządzenie, lecz przeniosą jedynie te aktualizowane
metadane, które są konieczne do pomyślnego zakończenia kolejnych operacji odczytu. Ta druga metoda
pozwala zredukować liczbę operacji dysku wymaganych w przypadku aplikacji, które nie wymagają gwarancji
spójności pliku.
Aby zrozumieć różnicę pomiędzy tymi dwoma typami kompletności, proszę rozważyć dwie cząstki metadanych
pliku: znacznik czasu ostatniej modyfikacji pliku (st_mtime) oraz długość pliku. Wszystkie operacje
zapisu zaktualizują znacznik czasu ostatniej modyfikacji pliku, lecz jedynie zapisy dodające dane na
końcu pliku, spowodują zmianę jego długości. Znacznik czasu ostatniej modyfikacji nie jest wymagany do
pomyślnego zakończenia operacji odczytu, w przeciwieństwie do długości pliku. Zatem O_DSYNC zagwarantuje
jedynie zaktualizowanie metadanej długości pliku (podczas gdy O_SYNC również metadanej znacznika czasu
ostatniej modyfikacji pliku).
Przed Linuksem 2.6.33, Linux implementował dla open() jedynie znacznik O_SYNC. Jednak gdy podało się ten
znacznik, większość systemów plików w rzeczywistości zapewniało równoważnik kompletności
zsynchronizowanego wejścia/wyjścia danych w sposób zapewniający spójność (tj. O_SYNC był zaimplementowany
w rzeczywistości jako ekwiwalent O_DSYNC).
Od Linuksa 2.6.33, zapewniona jest prawidłowa obsługa O_SYNC. Jednak aby zapewnić wsteczną kompatybilność
binarną, O_DSYNC zdefiniowano z tą samą wartością co historyczne O_SYNC, a O_SYNC zdefiniowano jako nową
(dwubitową) wartość znacznika, która zawiera wartość znacznika O_DSYNC. W ten sposób aplikacje
skompilowane z nowymi nagłówkami, otrzymają co najmniej zachowanie O_DSYNC przed Linuksem 2.6.33.
Różnice biblioteki C/jądra
Od glibc 2.26, funkcja opakowująca open() z glibc korzysta z wywołania systemowego openat(), zamiast z
wywołania systemowego jądra open(). Na niektórych architekturach działo się to także przed glibc 2.26.
STANDARDY
open()
creat()
openat()
POSIX.1-2008.
openat2(2) Linux.
Znaczniki O_DIRECT, O_NOATIME, O_PATH i O_TMPFILE są typowo linuksowe. Aby uzyskać ich definicje, należy
zdefiniować _GNU_SOURCE.
Znaczniki O_CLOEXEC, O_DIRECTORY i O_NOFOLLOW nie są określone w POSIX.1-2001, lecz są określone w
POSIX.1-2008. Od glibc 2.12, można uzyskać ich definicje definiując albo _POSIX_C_SOURCE z wartością
większą lub równą 200809L, albo _XOPEN_SOURCE z wartością większą lub równą 700. W glibc 2.11 i
wcześniejszych, można uzyskać te definicje definiując _GNU_SOURCE.
HISTORIA
open()
creat()
SVr4, 4.3BSD, POSIX.1-2001.
openat()
POSIX.1-2008. Linux 2.6.16, glibc 2.4.
UWAGI
W Linuksie, znacznik O_NONBLOCK jest niekiedy używany w przypadkach, gdy chce się otworzyć plik, ale
niekonieczne ma się zamiar odczytu lub zapisu z niego. Przykładowo można go użyć do otworzenia
urządzenia, w celu uzyskania deskryptora pliku do wykorzystania z ioctl(2).
Należy zauważyć, że open() może otwierać specjalne pliki urządzeń, lecz creat() nie może ich tworzyć.
Zamiast niego należy używać mknod(2).
Jeśli plik jest nowoutworzony, to jego pola st_atime, st_ctime, st_mtime (odpowiednio: czas ostatniego
dostępu, czas ostatniej zmiany statusu i czas ostatniej modyfikacji, zob. stat(2)) są ustawione na czas
bieżący i to samo dotyczy pól st_ctime i st_mtime katalogu nadrzędnego. Natomiast gdy plik jest
modyfikowany z powodu użycia znacznika O_TRUNC, jego pola st_ctime i st_mtime są ustawiane na czas
bieżący.
Pliki w katalogu /proc/pid/fd pokazują otwarte deskryptory pliku procesu o PID równym pid. Pliki w
katalogu /proc/pid/fdinfo pokazują jeszcze więcej informacji o tych deskryptorach pliku. Więcej
informacji o obu tych katalogach znajduje się w podręczniku proc(5).
Linuksowy plik nagłówkowy <asm/fcntl.h> nie definiuje O_ASYNC; definiowany jest jednak (wywodzący się z
BSD) synonim FASYNC.
Opisy otwartego pliku
Termin „opis otwartego pliku ” (ang. „open file description”) jest używany przez POSIX w odniesieniu do
wpisów w systemowej tablicy otwartych plików. W innych kontekstach, obiekt ten miewa również następujące
określenia (w nawiasach określenia angielskie): „obiekt otwartego pliku” („open file object”), „uchwyt
pliku” („file handle”), „wpis tablicy otwartych plików” („open file table entry”) albo — w żargonie
deweloperów jądra — plik struct („struct file”).
Gdy deskryptor pliku jest duplikowany (za pomocą dup(2) lub podobnego), to duplikat odnosi się do tego
samego opisu otwartego pliku, co pierwotny deskryptor pliku; oba deskryptory dzielą zatem przesunięcie
pliku i znaczniki statusu pliku. Takie dzielenie może również nastąpić między procesami: proces potomny
utworzony za pomocą fork(2) dziedziczy duplikaty deskryptorów pliku swojego rodzica, a te duplikaty
odnoszą się do tych samych opisów otwartego pliku.
Każde otwarcie pliku za pomocą open() tworzy nowy opis otwartego pliku; zatem może istnieć wiele opisów
otwartego pliku odnoszących do i-węzła pliku.
W Linuksie, można użyć operacji KCMP_FILE kcmp(2) do sprawdzenia, czy dwa deskryptory pliku (w tym samym
procesie lub w dwóch różnych procesach) odnoszą się do tego samego opisu otwartego pliku.
NFS
Jest wiele niedogodności w protokole podległym NFS, dotykających między innymi O_SYNC i O_NDELAY.
Na systemach NFS z włączonym mapowaniem UID-ów, open() może zwrócić deskryptor pliku, dla którego np.
żądania read(2) są zabronione przy ustawionym EACCES. Jest to związane ze sprawdzaniem uprawnień
odbywającym się na kliencie, ale to serwer wykonuje mapowanie UID-ów podczas żądań odczytu i zapisu.
FIFO
Otwarcie końca do odczytu lub końca do zapisu FIFO blokuje, do momentu otwarcia również drugiego z końców
(przez inny proces lub wątek). Więcej informacji w podręczniku fifo(7).
Tryb dostępu do pliku
W przeciwieństwie do innych wartości, jakie można podać we flags, wartości trybu dostępu: O_RDONLY,
O_WRONLYi O_RDWR nie określają pojedynczych bitów. Definiują one dwa bity niższego rzędu flags i są
zdefiniowane jako, odpowiednio, 0, 1 i 2. Innymi słowy, połączenie O_RDONLY | O_WRONLY jest błędem
logicznym, w szczególności nie ma takiego samego znaczenia jak O_RDWR.
Linux rezerwuje specjalny, niestandardowy tryb dostępu 3 (binarne 11) we flags, do następującego
znaczenia: sprawdź uprawnienia odczytu i zapisu pliku i zwróć deskryptor pliku, który nie może być użyty
do odczytu i do zapisu. Ten niestandardowy tryb dostępu jest wykorzystywany przez niektóre linuksowe
sterowniki w celu zwrócenia deskryptora pliku, przeznaczonego tylko do typowo „sterownikowych” działań
ioctl(2).
Celowość API openat() i innych API katalogowych deskryptorów pliku
openat() oraz inne wywołania systemowe i funkcje biblioteczne, które przyjmują jako argument deskryptor
pliku odnoszący się do katalogu (tj. execveat(2), faccessat(2), fanotify_mark(2), fchmodat(2),
fchownat(2), fspick(2), fstatat(2), futimesat(2), linkat(2), mkdirat(2), mknodat(2), mount_setattr(2),
move_mount(2), name_to_handle_at(2), open_tree(2), openat2(2), readlinkat(2), renameat(2), renameat2(2),
statx(2), symlinkat(2), unlinkat(2), utimensat(2), mkfifoat(3) i scandirat(3)) rozwiązują dwa problemy
starszych interfejsów, które je poprzedzały. Tu podano wyjaśnienie odnoszące się do wywołania openat(),
jednak analogicznie można je zastosować do pozostałych interfejsów.
Przede wszystkim openat() pozwala uniknąć aplikacjom wystąpienia sytuacji wyścigu, która może zachodzić
przy otwieraniu za pomocą open() plików w katalogach innych, niż bieżący katalog roboczy. Wyścig wynika z
tego, że pewna składowa ścieżki podanej open() mogła ulec zmianie równolegle z wywołaniem open(). Proszę
założyć na przykład, że próbujemy utworzyć plik kat1/kat2/xxx.zal, jeśli plik kat1/kat2/xxx istnieje.
Jednak pomiędzy sprawdzeniem istnienia i krokiem utworzenia pliku, kat1 lub kat2 (które mogą być
dowiązaniami symbolicznymi) mogą być zdefiniowane, aby wskazywać na inne położenia. Wyścigu można
uniknąć, otwierając deskryptor pliku katalogu docelowego, a następnie podając ten deskryptor pliku jako
argument dirfd do (przykładowo) fstatat(2) i openat(). Użycie deskryptora pliku dirfd ma także inne
zalety:
• deskryptor pliku jest stabilną referencją do katalogu, nawet gdy jego nazwa się zmieni oraz
• otwarty deskryptor pliku zapobiega odmontowaniu systemu plików, na którym się znajduje, podobnie jak
ma to miejsce w przypadku procesu, mającego swój bieżący katalog roboczy w danym systemie plików.
Po drugie, openat() pozwala na implementację „bieżącego katalogu roboczego” przypisanego wątkowi, za
pomocą deskryptora(-ów) pliku(-ów) zarządzanych przez aplikację (tę funkcjonalność można też uzyskać za
pomocą sztuczek opartych na korzystaniu z /proc/self/fd/dirfd, lecz jest to mniej wydajne).
Argument dirfd do tych API można pozyskać za pomocą open() lub openat() do otworzenia katalogu (ze
znacznikiem O_RDONLY albo O_PATH). Alternatywnie, taki deskryptor pliku można uzyskać stosując dirfd(3)
do strumienia katalogu utworzonego za pomocą opendir(3).
W omawianych API, gdy poda się argument dirfd równy AT_FDCWD albo podana ścieżka jest bezwzględna, API
obsługują swój argument ścieżki w taki sam sposób, jak odpowiadające im tradycyjne API. Jednak w tym
przypadku, wiele z API posiada argument flags, pozwalający na dostęp do funkcjonalności, która nie jest
dostępna w odpowiadającym im tradycyjnym API.
O_DIRECT
Znacznik O_DIRECT może nakładać ograniczenia (związane z wyrównaniem) na długości i adresie buforów
definiowanych w przestrzeni użytkownika oraz przesunięciu pliku w wejściu/wyjściu. W Linuksie,
ograniczenia związane z wyrównaniem różnią się w zależności od systemu plików i wersji jądra, mogą też
wcale nie występować. Obsługa niewyrównanych wejść/wyjść O_DIRECT również jest zróżnicowana; mogą one
albo zawieść z błędem EINVAL, albo awaryjnie skorzystać z buforowanego wejścia/wyjścia.
Od Linuksa 6.1, obsługa O_DIRECT i ograniczenia wyrównania związane z danym plikiem można sprawdzić za
pomocą statx(2), wykorzystując znacznik STATX_DIOALIGN. Obsługa STATX_DIOALIGN różni się w zależności od
systemu plików; więcej szczegółów w podręczniku statx(2).
Niektóre systemy plików zapewniają swoje interfejsy do odpytywania ograniczeń wyrównania O_DIRECT,
przykładowo jest to operacja XFS_IOC_DIOINFO w xfsctl(3). Gdy jednak tylko jest dostępny, należy
korzystać z STATX_DIOALIGN.
Jeśli żadne w powyższych nie jest dostępne, to obsługa bezpośredniego wejścia/wyjścia oraz ograniczenia
związane z wyrównaniem można odgadnąć jedynie na podstawie znanej charakterystyki systemu plików, danego
pliku, nośnika danych i wersji jądra. W Linuksie 2.4, większość systemu plików opartych na urządzeniach
blokowych wymagało, aby długości i adresy pamięci wszystkich segmentów wejścia/wyjścia, były
wielokrotnościami rozmiaru bloku systemu plików (zwykle 4096 bajtów). W Linuksie 2.6.0, to ograniczenie
poluzowano do logicznego rozmiaru bloku (zwykle 512 bajtów). Rozmiar logicznego bloku urządzenia
blokowego można sprawdzić za pomocą operacji BLKSSZGET ioctl(2) lub z powłoki, poleceniem:
blockdev --getss
Wejścia/wyjścia O_DIRECT nigdy nie należy uruchamiać równolegle z wywołaniem systemowym fork(2), jeśli
bufor pamięci jest przypisaniem prywatnym (obejmuje to wszystkie przypisania utworzone za pomocą
znacznika MAP_PRIVATE mmap(2); w tym pamięć przydzieloną do kopca oraz bufory przydzielone statycznie).
Każde takie wejście/wyjście, niezależnie od tego, czy zostanie przesłane poprzez interfejs
asynchronicznego wejścia/wyjścia, czy od innego wątku procesu, powinno być ukończone przed wywołaniem
fork(2). Jeśli tak się nie stanie, może dojść do uszkodzenia danych oraz niezdefiniowanego zachowania w
procesie macierzystym i potomnym. To ograniczenie nie ma zastosowania w przypadku, gdy bufory pamięci do
wejścia/wyjścia O_DIRECT utworzono za pomocą shmat(2) lub mmap(2) ze znacznikiem MAP_SHARED. Nie ma
zastosowania również wtedy, gdy w stosunku do bufora pamięci udzielono wskazówki MADV_DONTFORK za pomocą
madvise(2), co zapewnia, że nie będzie on dostępny dla potomka po wykonaniu fork(2).
Znacznik O_DIRECT wprowadzono w SGI IRIX, gdzie ograniczenia związane z wyrównaniem były podobne do
Linuksa 2.4. IRIX ma również wywołanie fcntl(2) do odpytywania o poprawne wyrównania i rozmiary. We
FreeBSD 4.x wprowadzono znacznik o tej samej nazwie, ale nieposiadający ograniczeń wyrównania.
Obsługę O_DIRECT dodano w Linuksie 2.4.10. Starsze jądra Linux ignorują ten znacznik. Niektóre systemy
plików mogą go nie implementować; wówczas zastosowanie znacznika spowoduje, że open() zawiedzie z błędem
EINVAL.
Aplikacje powinny unikać mieszania O_DIRECT i zwykłego wejścia/wyjścia w tym samym pliku, szczególnie w
nachodzących na siebie obszarach pliku. Nawet gdy system plików poprawnie obsługuje zagadnienia związane
ze spójnością danych w tej sytuacji, sumaryczna przepustowość wejścia/wyjścia będzie prawdopodobnie
gorsza, niż przy zdecydowaniu się na któryś z trybów. Aplikacje powinny również unikać mieszania
korzystania z mmap(2) na plikach, przy używaniu bezpośredniego wejścia/wyjścia do tych samych plików.
Zachowanie O_DIRECT w systemie NFS różni się od lokalnych systemów plików. Starsze jądra oraz jądra
skonfigurowane w pewien sposób mogą nie obsługiwać tego połączenia. Protokół NFS nie obsługuje
przekazywania znacznika serwerowi, zatem wejście/wyjście O_DIRECT pominie buforowanie strony tylko po
stronie klienta; serwer wciąż może buforować wejście/wyjście. Klient prosi serwer o uczynienie
wejścia/wyjścia synchronicznym, aby zachować synchroniczne zachowanie O_DIRECT. Niektóre serwery nie będą
się zachowywały wydajnie w takim przypadku, szczególnie jeśli rozmiar wejścia/wyjścia jest niewielki.
Niektóre serwery mogą być również skonfigurowane w ten sposób, aby informować klientów nieprawidłowo
(przedwcześnie) o osiągnięciu stabilnego nośnika przez wejście/wyjście; ta metoda unika uszczerbku
wydajności kosztem pewnego ryzyka utraty spójności danych w przypadku awarii zasilania serwera. Linuksowy
klient NFS nie narzuca ograniczeń związanych z wyrównaniem w przypadku wejścia/wyjścia O_DIRECT.
Podsumowując, O_DIRECT jest narzędziem o potencjalnie dużych możliwościach, którego należy używać ze
sporą dawką ostrożności. Zaleca się, aby aplikacje korzystające z O_DIRECT, traktowały go jako, domyślnie
wyłączoną, opcję poprawiającą wydajność.
USTERKI
Obecnie nie da się włączyć wejścia/wyjścia sterowanego sygnałem podając znacznik O_ASYNC przy wywołaniu
open(); należy użyć fcntl(2), aby włączyć ten znacznik.
Przy próbie określenia, czy jądro obsługuje funkcję O_TMPFILE, należy sprawdzać dwa różne kody błędu:
EISDIR i ENOENT.
Jeśli we flags poda się O_CREAT oraz O_DIRECTORY, a plik podany w ścieżce pathname nie istnieje, open()
utworzy zwykły plik (tj. O_DIRECTORY zostanie zignorowany).
ZOBACZ TAKŻE
chmod(2), chown(2), close(2), dup(2), fcntl(2), link(2), lseek(2), mknod(2), mmap(2), mount(2),
open_by_handle_at(2), openat2(2), read(2), socket(2), stat(2), umask(2), unlink(2), write(2), fopen(3),
acl(5), fifo(7), inode(7), path_resolution(7), symlink(7)
TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: 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. open(2)