table of contents
- bookworm-backports 1:4.23.1-1~bpo12+1
- testing 1:4.23.1-1
- unstable 1:4.23.1-1
open(2) | System Calls Manual | open(2) |
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);
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:
- 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¶
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¶
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.
2 maja 2024 r. | Linux man-pages 6.8 |