open(2) System Calls Manual open(2) NAZWA open, creat - otwiera i ewentualnie tworzy plik BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include 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 Wywolanie systemowe open() otwiera plik okreslony sciezka pathname. Jesli podany plik nie istnieje, moze byc opcjonalnie (jesli we flags podano O_CREAT) utworzony przez open(). Wartoscia zwracana przez open() jest deskryptor pliku: niewielka, calkowita liczba nieujemna, bedaca indeksem wpisu w tablicy otwartych deskryptorow plikow procesu. Deskryptor pliku jest uzywany w kolejnych wywolaniach systemowych (read(2), write(2), lseek(2), fcntl(2) itp.), w celu odniesienia sie do otwartego pliku. Deskryptor pliku zwracany przez pomyslne wywolanie bedzie najnizszym numerem deskryptora pliku, ktory nie jest aktualnie otwarty przez proces. Domyslnie, nowy deskryptor pliku jest ustawiany jako pozostajacy otwarty po wykonaniu przez execve(2) (tj. znacznik deskryptora pliku FD_CLOEXEC opisany w fcntl(2) jest poczatkowo wylaczony); mozna uzyc opisanego ponizej znacznika O_CLOEXEC aby zmienic to zachowanie. Przesuniecie pliku jest ustawiane na poczatek pliku (zob. lseek(2)). Wywolanie open() tworzy nowy opis otwartego pliku, wpis w systemowej tablicy otwartych plikow. Opis otwartego pliku zawiera przesuniecie pliku i znaczniki statusu pliku (zob. nizej). Deskryptor pliku odnosi sie do opisu otwartego pliku i na to odniesienie nie ma wplywu pozniejsze usuniecie sciezki pathname lub jej modyfikacja, w celu wskazania innego pliku. Wiecej informacji o opisach otwartego pliku zawarto w rozdziale UWAGI. Argument flags musi zawierac jeden z nastepujacych trybow dostepu: O_RDONLY, O_WRONLY lub O_RDWR. Stanowia one, odpowiednio, zadania otwarcia tylko do odczytu, tylko do zapisu, lub do odczytu i zapisu. Ponadto, we flags moze zsumowac bitowo (OR) zero lub wiecej znacznikow tworzenia pliku i znacznikow 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 pozostale znaczniki, wypisane ponizej. Rozroznieniem pomiedzy tymi dwoma grupami znacznikow jest fakt, ze znaczniki tworzenia pliku wplywaja na zachowanie samej operacji otwarcia, natomiast znaczniki statusu pliku wplywaja na zachowanie kolejnych operacji wejscia/wyjscia. Znaczniki statusu pliku mozna pobrac i (w niektorych przypadkach) zmodyfikowac; wiecej szczegolow w podreczniku fcntl(2). Oto pelna lista znacznikow tworzenia pliku i znacznikow statusu pliku: O_APPEND Plik jest otwierany w trybie dopisywania. Przed kazda operacja write(2), przesuniecie pliku jest ustawiane na koniec pliku, jak z lseek(2). Modyfikacja przesuniecia pliku i operacja zapisu jest przeprowadzana jako jeden, niepodzielny krok. O_APPEND moze prowadzic do uszkodzenia plikow na systemach plikow NFS, gdy wiecej niz jeden proces naraz dopisuje dane do pliku. Jest to zwiazane z faktem, ze NFS nie obsluguje dopisywania do pliku, wiec jadro klienta musi to zasymulowac, co nie moze zostac wykonane bez wyscigu. O_ASYNC Wlacza wejscie/wyjscie sterowane sygnalem: generuje sygnal (domyslnie SIGIO, ale mozna go zmienic za pomoca fcntl(2)), gdy wejscie lub wyjscie poprzez ten deskryptor pliku staje sie mozliwe. Ta funkcja jest dostepna jedynie dla terminali, pseudoterminali, gniazd i (od Linuksa 2.6) potokow oraz FIFO. Wiecej szczegolow mozna znalezc w podreczniku fcntl(2). Zob. tez USTERKI ponizej. O_CLOEXEC (od Linuksa 2.6.23) Wlacza znacznik zamkniecia-przy-wykonaniu dla nowego deskryptora pliku. Podanie tego znacznika umozliwia unikniecie przez program wykonywania dodatkowych operacji F_SETFD fcntl(2) w celu ustawienia znacznika FD_CLOEXEC. Prosze zauwazyc, ze korzystanie z tego znacznika jest niezbedne w niektorych programach wielowatkowych, poniewaz oddzielna operacja F_SETFD fcntl(2), ustawiajaca znacznik FD_CLOEXEC, nie zapobiega wystapieniu sytuacji wyscigu, gdy jeden watek otwiera deskryptor pliku, probujac ustawic swoj znacznik zamkniecia-przy-wykonaniu za pomoca fcntl(2), a w tym samym czasie inny watek dokonuje fork(2) oraz execve(2). W zaleznosci od kolejnosci wykonania, wyscig ten moze spowodowac nieoczekiwany wyciek deskryptora pliku zwroconego przez open(), do programu wykonywanego przez proces potomny utworzony przez fork(2) (jest to typ wyscigu, ktory jest teoretycznie mozliwy dla kazdego wywolania systemowego tworzacego deskryptor pliku, ktory powinien otrzymac znacznik zamkniecia-przy-wykonaniu, dlatego rozne inne linuksowe wywolania systemowe udostepniaja rownowaznik znacznika O_CLOEXEC, aby poradzic sobie z tym problemem). O_CREAT Jesli pathname nie istnieje, tworzy ja jako zwykly plik. Wlasciciel (identyfikator uzytkownika) nowego pliku jest ustawiany na efektywny identyfikator uzytkownika procesu. Wlasnosc grupy (identyfikator grupy) nowego pliku jest ustawiana na efektywny identyfikator grupy procesu (zachowanie Systemu V) lub na identyfikator grupy katalogu nadrzednego (zachowanie BSD). W Linuksie, wybor typu zachowania zalezy od ustawienia bitu trybu set-group-ID w katalogu nadrzednym: jesli bit ten jest ustawiony, wybierane jest zachowanie BSD; w przeciwnym razie, stosowane jest zachowanie Systemu V. W przypadku niektorych systemow plikow, zachowanie to zalezy rowniez od opcji montowania bsdgroups i sysvgroups, ktore opisano w podreczniku mount(8). Argument mode okresla bity trybu pliku, jakie maja byc zastosowane do nowo tworzonego pliku. Jesli nie poda sie O_CREAT ani O_TMPFILE we flags, to mode jest ignorowane (mozna je zatem podac jako 0 lub po prostu pominac). Argument mode musi byc okreslony, jesli we flags podano O_CREAT lub O_TMPFILE; jesli sie go nie poda, jako tryb pliku zostana uzyte jakies losowe bajty ze stosu. Efektywny tryb jest modyfikowany przez umask procesu, w zwykly sposob: pod nieobecnosc domyslnych list kontroli dostepu (ACL), trybem tworzonego pliku jest (mode & ~umask). Prosze zauwazyc, ze mode stosuje sie tylko do kolejnych dostepow do nowo tworzonego pliku; wywolanie open(), ktore tworzy plik tylko do odczytu, moze zwrocic rowniez deskryptor pliku do odczytu i do zapisu. Dla parametru mode udostepniono nastepujace stale symboliczne: S_IRWXU 00700 uzytkownik (wlasciciel pliku) ma prawa odczytu, zapisu i uruchamiania. S_IRUSR 00400 uzytkownik ma prawa odczytu. S_IWUSR 00200 uzytkownik ma prawa zapisu. S_IXUSR 00100 uzytkownik 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 maja prawa odczytu, zapisu i uruchamiania. S_IROTH 00004 inni maja prawa odczytu. S_IWOTH 00002 inni maja prawa zapisu. S_IXOTH 00001 inni maja prawa uruchamiania. Zgodnie z POSIX, wplyw ustawienia innych bitow w mode jest nieokreslony. W Linuksie, honorowane jest rowniez ustawienie nastepujacych bitow w mode: S_ISUID 0004000 bit set-user-ID S_ISGID 0002000 bit set-group-ID (zob. inode(7)). S_ISVTX 0001000 bit lepkosci (zob. inode(7)). O_DIRECT (od Linuksa 2.4.10) Powoduje probe zminimalizowania efektow zwiazanych z buforowaniem wejscia/wyjscia do i z tego pliku. Na ogol spowoduje to zmniejszenie wydajnosci, ale jest to przydatne w specyficznych sytuacjach, na przyklad gdy aplikacje buforuja we wlasnym zakresie. Wejscie/wyjscie dla pliku odbywa sie wowczas bezposrednio z/do buforow w przestrzeni uzytkownika. Sam znacznik O_DIRECT stara sie dokonywac transferu synchronicznie, ale nie daje gwarancji znacznika O_SYNC, ze dane i wymagane metadane sa transferowane. Aby zagwarantowac synchroniczne wejscie/wyjscie, oprocz O_DIRECT konieczne jest uzycie rowniez O_SYNC. Wiecej informacji w rozdziale UWAGI ponizej. Semantycznie podobny (lecz przestarzaly) interfejs dla urzadzen blokowych opisano w raw(8). O_DIRECTORY Jesli pathname nie jest katalogiem, spowoduje niepowodzenie otwarcia. Ten znacznik dodano w Linuksie 2.1.126, aby uniknac problemow blokowania uslug (DoS), gdy opendir(3) jest wywolane dla FIFO lub dla urzadzenia tasmowego. O_DSYNC Operacje zapisu pliku zakoncza sie zgodnie z wymaganiem kompletnosci zsynchronizowanego wejscia/wyjscia danych w sposob gwarantujacy spojnosc. W chwili powrotu write(2) (i podobnego), dane wyjsciowe zostaly juz przeniesione na wlasciwe urzadzenie, razem ze wszystkimi metadanymi pliku, ktore sa konieczne do pobrania tych danych (tzn. jest to rownowazne jak gdyby po kazdym write(2) wywolywac fdatasync(2)). Prosze zapoznac sie z UWAGAMI ponizej. O_EXCL Zapewnia, ze to wywolanie utworzy plik: jesli znacznik poda sie razem z O_CREAT, a sciezka pathname juz istnieje, to open() zawiedzie z bledem EEXIST. Po podaniu obu tych znacznikow, nie podaza sie za dowiazaniami symbolicznymi: jesli pathname jest dowiazaniem symbolicznym, to open() zawiedzie niezaleznie od tego, na co wskazuje to dowiazanie symboliczne. Co do zasady, zachowanie O_EXCL jest niezdefiniowane, jesli uzyje sie go bez O_CREAT. Jest jeden wyjatek: w Linuksie 2.6 i pozniejszych, O_EXCL mozna uzyc bez O_CREAT jesli pathname odnosi sie do urzadzenia blokowego. Jesli urzadzenie blokowe jest w uzyciu przez system (np. jest zamontowane), to open() zawiedzie z bledem EBUSY. W systemie plikow NFS O_EXCL jest obslugiwane tylko w NFSv3 lub pozniejszym na jadrze 2.6 lub pozniejszym. W srodowiskach NFS, gdzie nie zapewniono obslugi O_EXCL, programy ktore polegaja na nim, w celu dokonywania zadan blokowania, beda prowadzily do wyscigu. Przenosne programy, ktore chca przeprowadzac niepodzielne blokowanie pliku za pomoca pliku-blokady i musza unikac polegania na obsludze O_EXCL w NFS, moga tworzyc unikalny plik na tym samym systemie plikow (np. wykorzystujac nazwe stacji i PID) i uzywac link(2) do utworzenia dowiazania do pliku-blokady. Jesli link(2) zwroci 0, to utworzenie blokady sie powiodlo. W przeciwnym razie, nalezy uzyc stat(2) na unikalnym pliku, aby sprawdzic, czy ilosc jego dowiazan wzrosla do 2. W takiej sytuacji utworzenie blokady rowniez sie powiodlo. O_LARGEFILE (LFS) Pozwala na otwarcie plikow, ktorych rozmiarow nie mozna przedstawic w off_t (lecz mozna w off64_t). Konieczne jest zdefiniowanie makra _LARGEFILE64_SOURCE (przed wlaczeniem jakichkolwiek plikow naglowkowych) aby uzyskac jego definicje. Ustawienie makra sprawdzania cech _FILE_OFFSET_BITS na 64 (zamiast na O_LARGEFILE) jest preferowana metoda uzyskiwania dostepu do duzych plikow w systemach 32-bitowych (zob. feature_test_macros(7)). O_NOATIME (od Linuksa 2.6.8) Nie aktualizuje czasu ostatniego dostepu do pliku (st_atime w i-wezle) gdy plik jest odczytywany (read(2)). Znacznik ten mozna uzyc tylko, jesli spelniony zostanie jeden z ponizszych warunkow: o Efektywny UID procesu jest zgodny z UID-em wlasciciela pliku. o Proces wywolujacy ma przywilej CAP_FOWNER (ang. capability) w swojej przestrzeni nazw uzytkownika, a UID wlasciciela pliku ma przypisanie do tej przestrzeni nazw. Znacznik ten jest przeznaczony dla programow indeksujacych lub tworzacych kopie zapasowe, gdzie pozwala na znaczna redukcje aktywnosci dysku. Znacznik ten moze nie dzialac we wszystkich systemach plikow. Jednym z przykladow jest NFS, gdzie to serwer zarzadza czasami dostepu. O_NOCTTY Jesli pathname odnosi sie do urzadzenia terminalowego -- zob. tty(4) -- to nie stanie sie terminalem sterujacym procesu, nawet jesli proces takiego nie ma. O_NOFOLLOW Jesli koncowa skladowa (basename) sciezki pathname jest dowiazaniem symbolicznym, to otwarcie zawiedzie z bledem ELOOP. Dowiazania symboliczne wczesniejszych skladowych sciezki wciaz zostana rozwiniete (prosze zauwazyc, ze blad ELOOP, ktory moze sie zdarzyc w tym przypadku, jest nierozroznialny od sytuacji, gdy otwarcie zawiedzie, z powodu zbyt wielu dowiazan symbolicznych, ktore wystapily przy rozwiazywaniu wczesniejszych skladowych sciezki). Znacznik ten jest rozszerzeniem FreeBSD, ktory zostal dodany w Linuksie 2.1.126 i zostal pozniej wprowadzony jako standard w normie POSIX.1-2008. Zob. tez O_PATH ponizej. O_NONBLOCK lub O_NDELAY Plik jest otwierany w trybie nieblokujacym, o ile to mozliwe. Ani open() ani kolejne operacje wejscia/wyjscia, na zwroconym przez to wywolanie deskryptorze, nie spowoduja blokowania procesu wywolujacego. Prosze zauwazyc, ze ustawienie tego znacznika nie ma wplywu na dzialanie poll(2), select(2), epoll(7) i podobnych, poniewaz interfejsy te jedynie informuja wywolujacego o tym, gdy deskryptor pliku jest ,,gotowy" co oznacza, ze operacja wejscia/wyjscia na deskryptorze pliku ze znacznikiem O_NONBLOCK zdecydowanie nie prowadzilaby do zablokowania. Prosze zauwazyc, ze znacznik ten nie ma wplywu na zwykle pliki i urzadzenia blokowe tzn. operacja wejscia/wyjscia bedzie (chwilowo) blokowac, gdy wymagana jest aktywnosc urzadzenia, niezaleznie od ustawienia O_NONBLOCK. Poniewaz takie zachowanie O_NONBLOCK moze w przyszlosci byc zaimplementowane, aplikacje nie powinny zalezec od zachowania blokowania, przy podawaniu tego znacznika w przypadku zwyklych plikow i urzadzen blokowych. Szczegoly dotyczace obslugi FIFO (nazwanych potokow) mozna znalezc w podreczniku fifo(7). Opis wplywu znacznika O_NONBLOCK, w polaczeniu z blokadami obowiazujacymi (przymusowymi) oraz z dzierzawami pliku, znajduje sie w podreczniku fcntl(2). O_PATH (od Linuksa 2.6.39) Pozyskuje deskryptor pliku, ktorego mozna uzyc w dwoch celach: do wskazania polozenia w drzewie systemu plikow i do przeprowadzenia operacji, ktore dzialaja 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)) zawioda z bledem EBADF. Na wynikowym deskryptorze pliku mozna wykonac nastepujace operacje: o close(2). o fchdir(2), jesli deskryptor pliku odnosi sie do katalogu (od Linuksa 3.5). o fstat(2) (od Linuksa 3.6). o fstatfs(2) (od Linuksa 3.12). o Zduplikowanie deskryptora pliku (dup(2), F_DUPFD z fcntl(2), itp). o Uzyskanie i ustawienie znacznikow deskryptora pliku (F_GETFD i F_SETFD z fcntl(2)). o Pobranie znacznikow statusu otwartego pliku za pomoca operacji F_GETFL z fcntl(2): zwrocone znaczniki beda obejmowaly rowniez bit O_PATH. o Przekazanie deskryptora pliku jako argumentu dirfd do openat() i innych wywolan systemowych ,,*at()". Obejmuje to rowniez linkat(2) z AT_EMPTY_PATH (lub za pomoca procfs wykorzystujac AT_SYMLINK_FOLLOW) nawet, gdy plik nie jest katalogiem. o Przekazanie deskryptora pliku do innego procesu za pomoca gniazda domeny Uniksa (zob. SCM_RIGHTS w podreczniku unix(7)). Gdy O_PATH poda sie we flags, to bity znacznikow inne niz O_CLOEXEC, O_DIRECTORY i O_NOFOLLOW sa ignorowane. Otwarcie pliku lub katalogu ze znacznikiem O_PATH nie wymaga uprawnien do samego obiektu (lecz wymaga uprawnienia wykonania (przeszukiwania) na katalogach w skladowej sciezki). W zaleznosci od kolejnej operacji, moze byc wykonane sprawdzenie odpowiednich uprawnien pliku (np. fchdir(2) wymaga uprawnienia wykonania (przeszukania) na katalogu, do ktorego odnosi sie jego argument z deskryptorem pliku). Odmiennie, przy uzyskiwaniu odniesienia do obiektu systemu plikow za pomoca znacznika O_RDONLY, wymagane jest posiadanie przez wywolujacego uprawnienia odczytu, nawet gdy kolejna operacja (np. fchdir(2), fstat(2)) nie wymaga uprawnienia odczytu do obiektu. Jesli pathname jest dowiazaniem symbolicznym i podano rowniez znacznik O_NOFOLLOW, to wywolanie zwroci deskryptor pliku odnoszacy sie do dowiazania symbolicznego. Ten deskryptor pliku moze sluzyc jako argument dirfd w wywolaniach do fchownat(2), fstatat(2), linkat(2) i readlinkat(2) z pusta sciezka, aby wywolania dzialaly na samym dowiazaniu symbolicznym. Jesli pathname odnosi sie do punktu automatycznego montowania, ktory nie zostal jeszcze wyzwolony, tak wiec nie zamontowano w nim innego systemu plikow, to wywolanie zwroci deskryptor pliku odnoszacy sie do katalogu automatycznego montowania, bez wyzwalania montowania. Mozna nastepnie uzyc fstatfs(2), aby sprawdzic, czy jest to faktycznie niewyzwolony punkt automatycznego montowania (.f_type == AUTOFS_SUPER_MAGIC). Mozna uzyc O_PATH w przypadku zwyklych plikow, aby uzyskac funkcjonalnosc rownowazna O_EXEC z POSIX.1. Pozwala to na otwarcie pliku, do ktorego posiada sie uprawnienie wykonywania, ale nie posiada sie uprawnienia odczytu, a nastepnie wykonanie pliku, za pomoca krokow podobnych do ponizszych: char buf[PATH_MAX]; fd = open("jakis_program", O_PATH); snprintf(buf, PATH_MAX, "/proc/self/fd/%d", fd); execl(buf, "jakis_program", (char *) NULL); Deskryptor pliku O_PATH moze byc rowniez przekazany jako argument fexecve(3). O_SYNC Operacje zapisu na pliku zakoncza sie zgodnie z wymaganiem kompletnosci zsynchronizowanego wejscia/wyjscia pliku w sposob gwarantujacy spojnosc (odmiennie od zakonczenia zgodnie z wymaganiem kompletnosci zsynchronizowanego wejscia/wyjscia danych, udostepnianego przez O_DSYNC). W chwili powrotu write(2) (i podobnego), dane wyjsciowe i powiazane metadane pliku zostaly juz przeniesione na wlasciwe urzadzenie (tzn. jest to rownowazne jak gdyby po kazdym write(2) wywolywac fsync(2)). Prosze zapoznac sie z UWAGAMI ponizej. O_TMPFILE (od Linuksa 3.11) Tworzy nienazwany, zwykly plik tymczasowy. Argument pathname okresla katalog, w katalogu tym, w systemie plikow zostanie utworzony nienazwany i-wezel. Wszystko, co zostanie zapisane do wynikowego pliku, ulegnie utracie po zamknieciu ostatniego deskryptora pliku chyba, ze plik otrzyma nazwe. Ze znacznikiem O_TMPFILE nalezy uzyc O_RDWR lub O_WRONLY i, opcjonalnie, O_EXCL. Jesli nie poda sie O_EXCL, to mozna skorzystac z linkat(2) do utworzenia dowiazania do systemu plikow, czyniac plik stalym, za pomoca kodu podobnego do ponizszego: char path[PATH_MAX]; fd = open("/sciezka/do/katalogu", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); /* Wejscie/wyjscie na 'fd'... */ linkat(fd, "", AT_FDCWD, "/sciezka/do/pliku", AT_EMPTY_PATH); /* Jesli wywolujacy nie ma przywileju CAP_DAC_READ_SEARCH (potrzebnego do uzycia AT_EMPTY_PATH z linkat(2)), i system plikow proc(5) jest zamontowany, to powyzsze wywolanie linkat(2) mozna zastapic przez: snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd); linkat(AT_FDCWD, path, AT_FDCWD, "/sciezka/do/pliku", AT_SYMLINK_FOLLOW); */ W tym przypadku argument mode open() okresla tryb uprawnien pliku, podobnie jak przy O_CREAT. Podanie O_EXCL w polaczeniu z O_TMPFILE zapobiega mozliwosci utworzenia dowiazania do systemu plikow w powyzszy sposob (prosze zauwazyc, ze znaczenie O_EXCL w tym przypadku rozni sie od znaczenia O_EXCL w pozostalych przypadkach). Istnieja dwa glowne zastosowania O_TMPFILE: o Usprawniona funkcjonalnosc tmpfile(3): tworzenie plikow tymczasowych bez ryzyka wystapienia wyscigu, ktore: (1) sa automatycznie usuwane po zamknieciu; (2) nie da sie do nich dostac za pomoca zadnej sciezki; (3) nie sa przedmiotem atakow na dowiazania symboliczne oraz (4) nie wymagaja wymyslania przez wywolujacego unikatowych nazw. o Tworzenie plikow poczatkowo niewidocznych, ktore sa nastepnie wypelniane danymi i dostosowywane w celu posiadania wlasciwych atrybutow systemu plikow (fchown(2), fchmod(2), fsetxattr(2) itp.) przed niepodzielnym utworzeniem dowiazania do systemu plikow, w stanie juz w pelni uksztaltowanym (za pomoca opisanego wyzej linkat(2)). O_TMPFILE wymaga obslugi w podleglym systemie plikow; jedynie podzbior linuksowych systemow plikow ja zapewnia. W pierwotnej implementacji, obsluge zapewnialy system plikow ext2, ext3, ext4, UDF, Minix i tmpfs. Nastepnie dodano obsluge kolejnych systemow plikow: XFS (Linux 3.15); Btrfs (Linux 3.16); F2FS (Linux 3.16) oraz ubifs (Linux 4.9) O_TRUNC Jesli plik juz istnieje, jest zwyklym plikiem i tryb dostepu pozwala na zapis (tzn. jest to O_RDWR lub O_WRONLY), to plik ten zostanie obciety do zerowej dlugosci. Jesli plik to FIFO lub urzadzenie terminalowe, to znacznik O_TRUNC jest ignorowany. W pozostalych przypadkach efekt uzycia znacznika O_TRUNC jest nieokreslony. creat() Wywolanie creat() jest rownowazne wywolaniu open() z argumentem flags ustawionym na O_CREAT|O_WRONLY|O_TRUNC. openat() Wywolanie systemowe openat() operuje w dokladnie taki sam sposob jak open(), z wyjatkiem roznic opisanych tutaj. Argument dirfd jest uzywany w polaczeniu z argumentem pathname, w nastepujacy sposob: o Jesli sciezka podana w pathname jest bezwzgledna, to dirfd jest ignorowane. o Jesli sciezka podana w pathname jest wzgledna, a dirfd ma wartosc specjalna AT_FDCWD, to pathname jest interpretowana wzgledem biezacego katalogu roboczego procesu wywolujacego (jak open()). o Jesli sciezka podana w pathname jest wzgledna, to jest interpretowana wzgledem katalogu, do ktorego odnosi sie deskryptor pliku dirfd (zamiast w odniesieniu do biezacego katalogu roboczego procesu wywolujacego, jak czyni to open() w stosunku do sciezek wzglednych). W tym przypadku, dirfd musi byc katalogiem, ktory byl otwarty do odczytu (O_RDONLY) lub za pomoca znacznika O_PATH. Jesli sciezka podana w pathname jest wzgledna, a dirfd nie jest prawidlowym deskryptorem pliku, to wystapi blad (EBADF; mozna zatem posluzyc sie tym mechanizmem do upewnienia sie, ze sciezka pathname jest bezwzgledna, podajac w dirfd nieprawidlowy numer deskryptora). openat2(2) Wywolanie systemowe openat2(2) jest rozszerzeniem openat() i udostepnia nadzbior funkcji wobec openat(). Jest udokumentowane oddzielnie, w podreczniku openat2(2). WARTOSC ZWRACANA W przypadku powodzenia, open(), openat() i creat() zwracaja nowy deskryptor pliku (liczbe nieujemna). W razie wystapienia bledu zwracane jest -1 i ustawiane errno wskazujac blad. BLEDY open(), openat() i creat() moga zawiesc z powodu nastepujacych bledow: EACCES Zadany dostep do pliku nie jest dozwolony, odmowiono uprawnienia przeszukiwania dla jednego z katalogow skladowych sciezki pathname, plik jeszcze nie istnieje i nie dozwolono na dostep do zapisu do katalogu nadrzednego (zob. tez path_resolution(7)). EACCES Gdy podano O_CREAT, wlaczona jest kontrolka systemowa sysctl protected_fifos lub protected_regular, plik juz istnieje i jest FIFO lub zwyklym plikiem, wlascicielem pliku nie jest ani biezacy uzytkownik, ani wlasciciel katalogu nadrzednego oraz katalog nadrzedny jest zapisywalny zarowno dla wszystkich lub dla grupy, jak i ma ustawiony bit lepkosci. Wiecej szczegolow w opisach /proc/sys/fs/protected_fifos i /proc/sys/fs/protected_regular w podreczniku proc_sys_fs(5). EBADF (openat()) pathname jest wzgledne, lecz dirfd nie wynosi ani AT_FDCWD, ani nie jest prawidlowym deskryptorem pliku. EBUSY We flags podano O_EXCL, a sciezka pathname odnosi sie do urzadzenia blokowego, ktore jest w uzyciu przez system (np. jest zamontowane). EDQUOT Podano O_CREAT, plik nie istnieje, a przydzial blokow dyskowych lub i-wezlow dla uzytkownika w systemie plikow wyczerpal sie. EEXIST pathname juz istnieje, a uzyto O_CREAT i O_EXCL. EFAULT pathname wskazuje poza dostepna dla uzytkownika przestrzen adresowa. EFBIG Zob. EOVERFLOW. EINTR Wywolanie zostalo przerwane przez procedure obslugi sygnalu, w trakcie zablokowania w oczekiwaniu na ukonczenie otwarcia na powolnym (np. FIFO; zob. fifo(7)) urzadzeniu; zob. signal(7). EINVAL System plikow nie obsluguje znacznika O_DIRECT. Wiecej informacji w UWAGACH. EINVAL Nieprawidlowa wartosc we flags. EINVAL We flags podano O_TMPFILE, lecz nie podano O_WRONLY, ani O_RDWR. EINVAL We flags podano O_CREAT, lecz ostatnia skladowa (,,basename") sciezki pathname nowego pliku jest nieprawidlowa (np. zawiera znaki, ktore nie sa dozwolone w danym systemie plikow). EINVAL Ostatnia skladowa (,,basename") sciezki pathname jest nieprawidlowa (np. zawiera znaki, ktore nie sa dozwolone w danym systemie plikow). EISDIR pathname odnosi sie do katalogu, a zadany byl dostep z prawem zapisu (tzn. ustawione bylo O_WRONLY lub O_RDWR). EISDIR pathname odnosi sie do istniejacego katalogu, we flags podano O_TMPFILE i jeden z: O_WRONLY lub O_RDWR, lecz ta wersja jadra nie zapewnia funkcjonalnosci O_TMPFILE. ELOOP Podczas rozwiazywania pathname napotkano zbyt wiele dowiazan symbolicznych. ELOOP pathname byla dowiazaniem symbolicznym, a we flags podano O_NOFOLLOW, lecz nie podano O_PATH. EMFILE Osiagnieto limit liczby otwartych deskryptorow pliku na proces (zob. opis RLIMIT_NOFILE w podreczniku getrlimit(2)). ENAMETOOLONG pathname bylo zbyt dlugie. ENFILE Zostalo osiagniete systemowe ograniczenie na calkowita liczbe otwartych plikow. ENODEV pathname odnosi sie do pliku urzadzenia specjalnego, a odpowiadajace mu urzadzenie nie istnieje (jest to blad w jadrze Linux; w takiej sytuacji powinno byc zwracane ENXIO). ENOENT Nie ustawiono O_CREAT, a nazwany plik nie istnieje. ENOENT Skladowa pathname, ktora powinna byc katalogiem nie istnieje lub jest wiszacym dowiazaniem symbolicznym. ENOENT pathname odnosi sie do nieistniejacego katalogu, we flags podano O_TMPFILE i jeden z: O_WRONLY lub O_RDWR, lecz ta wersja jadra nie zapewnia funkcjonalnosci O_TMPFILE. ENOMEM Nazwany plik jest FIFO, lecz nie mozna przydzielic pamieci dla bufora FIFO, poniewaz osiagnieto bezwzgledny limit pamieci przydzielanej potokom na uzytkownika, a wywolujacy nie jest uprzywilejowany; zob. pipe(7). ENOMEM Brak pamieci jadra. ENOSPC Gdy pathname mialo byc utworzone, okazalo sie, ze na urzadzeniu na ktorym mialo sie znajdowac brak miejsca na nowy plik. ENOTDIR Skladowa uzyta w pathname jako katalog w rzeczywistosci nie jest katalogiem lub podano O_DIRECTORY, a pathname nie bylo katalogiem. ENOTDIR (openat()) pathname jest sciezka wzgledna a dirfd jest deskryptorem pliku odnoszacym sie do pliku zamiast do katalogu. ENXIO Podano O_NONBLOCK | O_WRONLY, plik o zadanej nazwie stanowi FIFO i nie jest ono otwarte dla zadnego procesu do odczytu. ENXIO Plik jest specjalnym plikiem urzadzenia, a odpowiadajace mu urzadzenie nie istnieje. ENXIO Plik jest gniazdem domeny Uniksa. EOPNOTSUPP System plikow zawierajacy pathname nie obsluguje O_TMPFILE. EOVERFLOW Sciezka pathname odnosi sie do zwyklego pliku, ktory jest zbyt duzy, aby moc go otworzyc. Zwykle jest to sytuacja, w ktorej aplikacja skompilowana na platformie 32-bitowej bez -D_FILE_OFFSET_BITS=64 probuje otworzyc plik o rozmiarze ponad (1<<31)-1 bajtow; zob. tez O_LARGEFILE powyzej. Jest to kod bledu wynikajacy z POSIX.1; przed Linuksem 2.6.24, Linux w takiej sytuacji generowal blad EFBIG. EPERM Podano znacznik O_NOATIME, ale efektywny identyfikator uzytkownika wywolujacego nie rownal sie wlascicielowi pliku, a wywolujacy nie byl uprzywilejowany. EPERM Operacja zablokowana, z powodu zapieczetowania pliku (ang. file seal); zob. fcntl(2). EROFS pathname odnosi sie do pliku na systemie plikow tylko do odczytu, a zadano otwarcia w trybie do zapisu. ETXTBSY pathname odnosi sie do wykonywalnego obrazu, ktory obecnie jest wykonywany, a zazadano dostepu do zapisu. ETXTBSY pathname odnosi sie do pliku, uzywanego obecnie jako pliku wymiany, a podano znacznik O_TRUNC. ETXTBSY pathname odnosi sie do pliku aktualnie odczytywanego przez jadro (np. do zaladowania modulu/oprogramowania ukladowego), a zazadano dostepu do zapisu. EWOULDBLOCK Podano znacznik O_NONBLOCK, a na pliku utrzymywana jest niezgodna dzierzawa (zob. fcntl(2)). WERSJE (Niezdefiniowany) wynik O_RDONLY | O_TRUNC rozni sie w zaleznosci od implementacji. W wielu systemach plik jest faktycznie przycinany. Synchronizowane wejscie/wyjscie Opcja POSIX.1-2008 ,,synchronized I/O" okresla rozne warianty synchronizowanego wejscia/wyjscia i podaje znaczniki O_SYNC, O_DSYNC i O_RSYNC open() jako przeznaczone do kontrolowania oczekiwanego zachowania. Niezaleznie od tego, czy dana implementacja obsluguje te opcje, obowiazkowa jest obsluga co najmniej O_SYNC w przypadku zwyklych plikow. Linux implementuje O_SYNC i O_DSYNC, lecz nie O_RSYNC. Poniekad niewlasciwie, glibc definiuje O_RSYNC jako majace te sama wartosc co O_SYNC (O_RSYNC jest zdefiniowane w linuksowym pliku naglowkowym na architekturze HP PA-RISC, lecz nie jest uzywane). O_SYNC zapewnia kompletnosc zsynchronizowanego wejscia/wyjscia pliku w sposob gwarantujacy spojnosc tzn. operacje zapisu przenosza dane i wszystkie powiazane metadane na przedmiotowe urzadzenie. O_DSYNC zapewnia kompletnosc zsynchronizowanego wejscia/wyjscia danych w sposob gwarantujacy spojnosc tzn. operacje zapisu przenosza dane na przedmiotowe urzadzenie, lecz przeniosa jedynie te aktualizowane metadane, ktore sa konieczne do pomyslnego zakonczenia kolejnych operacji odczytu. Ta druga metoda pozwala zredukowac liczbe operacji dysku wymaganych w przypadku aplikacji, ktore nie wymagaja gwarancji spojnosci pliku. Aby zrozumiec roznice pomiedzy tymi dwoma typami kompletnosci, prosze rozwazyc dwie czastki metadanych pliku: znacznik czasu ostatniej modyfikacji pliku (st_mtime) oraz dlugosc pliku. Wszystkie operacje zapisu zaktualizuja znacznik czasu ostatniej modyfikacji pliku, lecz jedynie zapisy dodajace dane na koncu pliku, spowoduja zmiane jego dlugosci. Znacznik czasu ostatniej modyfikacji nie jest wymagany do pomyslnego zakonczenia operacji odczytu, w przeciwienstwie do dlugosci pliku. Zatem O_DSYNC zagwarantuje jedynie zaktualizowanie metadanej dlugosci pliku (podczas gdy O_SYNC rowniez metadanej znacznika czasu ostatniej modyfikacji pliku). Przed Linuksem 2.6.33, Linux implementowal dla open() jedynie znacznik O_SYNC. Jednak gdy podalo sie ten znacznik, wiekszosc systemow plikow w rzeczywistosci zapewnialo rownowaznik kompletnosci zsynchronizowanego wejscia/wyjscia danych w sposob zapewniajacy spojnosc (tj. O_SYNC byl zaimplementowany w rzeczywistosci jako ekwiwalent O_DSYNC). Od Linuksa 2.6.33, zapewniona jest prawidlowa obsluga O_SYNC. Jednak aby zapewnic wsteczna kompatybilnosc binarna, O_DSYNC zdefiniowano z ta sama wartoscia co historyczne O_SYNC, a O_SYNC zdefiniowano jako nowa (dwubitowa) wartosc znacznika, ktora zawiera wartosc znacznika O_DSYNC. W ten sposob aplikacje skompilowane z nowymi naglowkami, otrzymaja co najmniej zachowanie O_DSYNC przed Linuksem 2.6.33. Roznice biblioteki C/jadra Od glibc 2.26, funkcja opakowujaca open() z glibc korzysta z wywolania systemowego openat(), zamiast z wywolania systemowego jadra open(). Na niektorych architekturach dzialo sie to takze przed glibc 2.26. STANDARDY open() creat() openat() POSIX.1-2008. openat2(2) Linux. Znaczniki O_DIRECT, O_NOATIME, O_PATH i O_TMPFILE sa typowo linuksowe. Aby uzyskac ich definicje, nalezy zdefiniowac _GNU_SOURCE. Znaczniki O_CLOEXEC, O_DIRECTORY i O_NOFOLLOW nie sa okreslone w POSIX.1-2001, lecz sa okreslone w POSIX.1-2008. Od glibc 2.12, mozna uzyskac ich definicje definiujac albo _POSIX_C_SOURCE z wartoscia wieksza lub rowna 200809L, albo _XOPEN_SOURCE z wartoscia wieksza lub rowna 700. W glibc 2.11 i wczesniejszych, mozna uzyskac te definicje definiujac _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 uzywany w przypadkach, gdy chce sie otworzyc plik, ale niekonieczne ma sie zamiar odczytu lub zapisu z niego. Przykladowo mozna go uzyc do otworzenia urzadzenia, w celu uzyskania deskryptora pliku do wykorzystania z ioctl(2). Nalezy zauwazyc, ze open() moze otwierac specjalne pliki urzadzen, lecz creat() nie moze ich tworzyc. Zamiast niego nalezy uzywac mknod(2). Jesli plik jest nowoutworzony, to jego pola st_atime, st_ctime, st_mtime (odpowiednio: czas ostatniego dostepu, czas ostatniej zmiany statusu i czas ostatniej modyfikacji, zob. stat(2)) sa ustawione na czas biezacy i to samo dotyczy pol st_ctime i st_mtime katalogu nadrzednego. Natomiast gdy plik jest modyfikowany z powodu uzycia znacznika O_TRUNC, jego pola st_ctime i st_mtime sa ustawiane na czas biezacy. Pliki w katalogu /proc/pid/fd pokazuja otwarte deskryptory pliku procesu o PID rownym pid. Pliki w katalogu /proc/pid/fdinfo pokazuja jeszcze wiecej informacji o tych deskryptorach pliku. Wiecej informacji o obu tych katalogach znajduje sie w podreczniku proc(5). Linuksowy plik naglowkowy nie definiuje O_ASYNC; definiowany jest jednak (wywodzacy sie z BSD) synonim FASYNC. Opisy otwartego pliku Termin ,,opis otwartego pliku " (ang. ,,open file description") jest uzywany przez POSIX w odniesieniu do wpisow w systemowej tablicy otwartych plikow. W innych kontekstach, obiekt ten miewa rowniez nastepujace okreslenia (w nawiasach okreslenia angielskie): ,,obiekt otwartego pliku" (,,open file object"), ,,uchwyt pliku" (,,file handle"), ,,wpis tablicy otwartych plikow" (,,open file table entry") albo -- w zargonie deweloperow jadra -- plik struct (,,struct file"). Gdy deskryptor pliku jest duplikowany (za pomoca dup(2) lub podobnego), to duplikat odnosi sie do tego samego opisu otwartego pliku, co pierwotny deskryptor pliku; oba deskryptory dziela zatem przesuniecie pliku i znaczniki statusu pliku. Takie dzielenie moze rowniez nastapic miedzy procesami: proces potomny utworzony za pomoca fork(2) dziedziczy duplikaty deskryptorow pliku swojego rodzica, a te duplikaty odnosza sie do tych samych opisow otwartego pliku. Kazde otwarcie pliku za pomoca open() tworzy nowy opis otwartego pliku; zatem moze istniec wiele opisow otwartego pliku odnoszacych do i-wezla pliku. W Linuksie, mozna uzyc operacji KCMP_FILE kcmp(2) do sprawdzenia, czy dwa deskryptory pliku (w tym samym procesie lub w dwoch roznych procesach) odnosza sie do tego samego opisu otwartego pliku. NFS Jest wiele niedogodnosci w protokole podleglym NFS, dotykajacych miedzy innymi O_SYNC i O_NDELAY. Na systemach NFS z wlaczonym mapowaniem UID-ow, open() moze zwrocic deskryptor pliku, dla ktorego np. zadania read(2) sa zabronione przy ustawionym EACCES. Jest to zwiazane ze sprawdzaniem uprawnien odbywajacym sie na kliencie, ale to serwer wykonuje mapowanie UID-ow podczas zadan odczytu i zapisu. FIFO Otwarcie konca do odczytu lub konca do zapisu FIFO blokuje, do momentu otwarcia rowniez drugiego z koncow (przez inny proces lub watek). Wiecej informacji w podreczniku fifo(7). Tryb dostepu do pliku W przeciwienstwie do innych wartosci, jakie mozna podac we flags, wartosci trybu dostepu: O_RDONLY, O_WRONLYi O_RDWR nie okreslaja pojedynczych bitow. Definiuja one dwa bity nizszego rzedu flags i sa zdefiniowane jako, odpowiednio, 0, 1 i 2. Innymi slowy, polaczenie O_RDONLY | O_WRONLY jest bledem logicznym, w szczegolnosci nie ma takiego samego znaczenia jak O_RDWR. Linux rezerwuje specjalny, niestandardowy tryb dostepu 3 (binarne 11) we flags, do nastepujacego znaczenia: sprawdz uprawnienia odczytu i zapisu pliku i zwroc deskryptor pliku, ktory nie moze byc uzyty do odczytu i do zapisu. Ten niestandardowy tryb dostepu jest wykorzystywany przez niektore linuksowe sterowniki w celu zwrocenia deskryptora pliku, przeznaczonego tylko do typowo ,,sterownikowych" dzialan ioctl(2). Celowosc API openat() i innych API katalogowych deskryptorow pliku openat() oraz inne wywolania systemowe i funkcje biblioteczne, ktore przyjmuja jako argument deskryptor pliku odnoszacy sie 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)) rozwiazuja dwa problemy starszych interfejsow, ktore je poprzedzaly. Tu podano wyjasnienie odnoszace sie do wywolania openat(), jednak analogicznie mozna je zastosowac do pozostalych interfejsow. Przede wszystkim openat() pozwala uniknac aplikacjom wystapienia sytuacji wyscigu, ktora moze zachodzic przy otwieraniu za pomoca open() plikow w katalogach innych, niz biezacy katalog roboczy. Wyscig wynika z tego, ze pewna skladowa sciezki podanej open() mogla ulec zmianie rownolegle z wywolaniem open(). Prosze zalozyc na przyklad, ze probujemy utworzyc plik kat1/kat2/xxx.zal, jesli plik kat1/kat2/xxx istnieje. Jednak pomiedzy sprawdzeniem istnienia i krokiem utworzenia pliku, kat1 lub kat2 (ktore moga byc dowiazaniami symbolicznymi) moga byc zdefiniowane, aby wskazywac na inne polozenia. Wyscigu mozna uniknac, otwierajac deskryptor pliku katalogu docelowego, a nastepnie podajac ten deskryptor pliku jako argument dirfd do (przykladowo) fstatat(2) i openat(). Uzycie deskryptora pliku dirfd ma takze inne zalety: o deskryptor pliku jest stabilna referencja do katalogu, nawet gdy jego nazwa sie zmieni oraz o otwarty deskryptor pliku zapobiega odmontowaniu systemu plikow, na ktorym sie znajduje, podobnie jak ma to miejsce w przypadku procesu, majacego swoj biezacy katalog roboczy w danym systemie plikow. Po drugie, openat() pozwala na implementacje ,,biezacego katalogu roboczego" przypisanego watkowi, za pomoca deskryptora(-ow) pliku(-ow) zarzadzanych przez aplikacje (te funkcjonalnosc mozna tez uzyskac za pomoca sztuczek opartych na korzystaniu z /proc/self/fd/dirfd, lecz jest to mniej wydajne). Argument dirfd do tych API mozna pozyskac za pomoca open() lub openat() do otworzenia katalogu (ze znacznikiem O_RDONLY albo O_PATH). Alternatywnie, taki deskryptor pliku mozna uzyskac stosujac dirfd(3) do strumienia katalogu utworzonego za pomoca opendir(3). W omawianych API, gdy poda sie argument dirfd rowny AT_FDCWD albo podana sciezka jest bezwzgledna, API obsluguja swoj argument sciezki w taki sam sposob, jak odpowiadajace im tradycyjne API. Jednak w tym przypadku, wiele z API posiada argument flags, pozwalajacy na dostep do funkcjonalnosci, ktora nie jest dostepna w odpowiadajacym im tradycyjnym API. O_DIRECT Znacznik O_DIRECT moze nakladac ograniczenia (zwiazane z wyrownaniem) na dlugosci i adresie buforow definiowanych w przestrzeni uzytkownika oraz przesunieciu pliku w wejsciu/wyjsciu. W Linuksie, ograniczenia zwiazane z wyrownaniem roznia sie w zaleznosci od systemu plikow i wersji jadra, moga tez wcale nie wystepowac. Obsluga niewyrownanych wejsc/wyjsc O_DIRECT rowniez jest zroznicowana; moga one albo zawiesc z bledem EINVAL, albo awaryjnie skorzystac z buforowanego wejscia/wyjscia. Od Linuksa 6.1, obsluga O_DIRECT i ograniczenia wyrownania zwiazane z danym plikiem mozna sprawdzic za pomoca statx(2), wykorzystujac znacznik STATX_DIOALIGN. Obsluga STATX_DIOALIGN rozni sie w zaleznosci od systemu plikow; wiecej szczegolow w podreczniku statx(2). Niektore systemy plikow zapewniaja swoje interfejsy do odpytywania ograniczen wyrownania O_DIRECT, przykladowo jest to operacja XFS_IOC_DIOINFO w xfsctl(3). Gdy jednak tylko jest dostepny, nalezy korzystac z STATX_DIOALIGN. Jesli zadne w powyzszych nie jest dostepne, to obsluga bezposredniego wejscia/wyjscia oraz ograniczenia zwiazane z wyrownaniem mozna odgadnac jedynie na podstawie znanej charakterystyki systemu plikow, danego pliku, nosnika danych i wersji jadra. W Linuksie 2.4, wiekszosc systemu plikow opartych na urzadzeniach blokowych wymagalo, aby dlugosci i adresy pamieci wszystkich segmentow wejscia/wyjscia, byly wielokrotnosciami rozmiaru bloku systemu plikow (zwykle 4096 bajtow). W Linuksie 2.6.0, to ograniczenie poluzowano do logicznego rozmiaru bloku (zwykle 512 bajtow). Rozmiar logicznego bloku urzadzenia blokowego mozna sprawdzic za pomoca operacji BLKSSZGET ioctl(2) lub z powloki, poleceniem: blockdev --getss Wejscia/wyjscia O_DIRECT nigdy nie nalezy uruchamiac rownolegle z wywolaniem systemowym fork(2), jesli bufor pamieci jest przypisaniem prywatnym (obejmuje to wszystkie przypisania utworzone za pomoca znacznika MAP_PRIVATE mmap(2); w tym pamiec przydzielona do kopca oraz bufory przydzielone statycznie). Kazde takie wejscie/wyjscie, niezaleznie od tego, czy zostanie przeslane poprzez interfejs asynchronicznego wejscia/wyjscia, czy od innego watku procesu, powinno byc ukonczone przed wywolaniem fork(2). Jesli tak sie nie stanie, moze dojsc do uszkodzenia danych oraz niezdefiniowanego zachowania w procesie macierzystym i potomnym. To ograniczenie nie ma zastosowania w przypadku, gdy bufory pamieci do wejscia/wyjscia O_DIRECT utworzono za pomoca shmat(2) lub mmap(2) ze znacznikiem MAP_SHARED. Nie ma zastosowania rowniez wtedy, gdy w stosunku do bufora pamieci udzielono wskazowki MADV_DONTFORK za pomoca madvise(2), co zapewnia, ze nie bedzie on dostepny dla potomka po wykonaniu fork(2). Znacznik O_DIRECT wprowadzono w SGI IRIX, gdzie ograniczenia zwiazane z wyrownaniem byly podobne do Linuksa 2.4. IRIX ma rowniez wywolanie fcntl(2) do odpytywania o poprawne wyrownania i rozmiary. We FreeBSD 4.x wprowadzono znacznik o tej samej nazwie, ale nieposiadajacy ograniczen wyrownania. Obsluge O_DIRECT dodano w Linuksie 2.4.10. Starsze jadra Linux ignoruja ten znacznik. Niektore systemy plikow moga go nie implementowac; wowczas zastosowanie znacznika spowoduje, ze open() zawiedzie z bledem EINVAL. Aplikacje powinny unikac mieszania O_DIRECT i zwyklego wejscia/wyjscia w tym samym pliku, szczegolnie w nachodzacych na siebie obszarach pliku. Nawet gdy system plikow poprawnie obsluguje zagadnienia zwiazane ze spojnoscia danych w tej sytuacji, sumaryczna przepustowosc wejscia/wyjscia bedzie prawdopodobnie gorsza, niz przy zdecydowaniu sie na ktorys z trybow. Aplikacje powinny rowniez unikac mieszania korzystania z mmap(2) na plikach, przy uzywaniu bezposredniego wejscia/wyjscia do tych samych plikow. Zachowanie O_DIRECT w systemie NFS rozni sie od lokalnych systemow plikow. Starsze jadra oraz jadra skonfigurowane w pewien sposob moga nie obslugiwac tego polaczenia. Protokol NFS nie obsluguje przekazywania znacznika serwerowi, zatem wejscie/wyjscie O_DIRECT pominie buforowanie strony tylko po stronie klienta; serwer wciaz moze buforowac wejscie/wyjscie. Klient prosi serwer o uczynienie wejscia/wyjscia synchronicznym, aby zachowac synchroniczne zachowanie O_DIRECT. Niektore serwery nie beda sie zachowywaly wydajnie w takim przypadku, szczegolnie jesli rozmiar wejscia/wyjscia jest niewielki. Niektore serwery moga byc rowniez skonfigurowane w ten sposob, aby informowac klientow nieprawidlowo (przedwczesnie) o osiagnieciu stabilnego nosnika przez wejscie/wyjscie; ta metoda unika uszczerbku wydajnosci kosztem pewnego ryzyka utraty spojnosci danych w przypadku awarii zasilania serwera. Linuksowy klient NFS nie narzuca ograniczen zwiazanych z wyrownaniem w przypadku wejscia/wyjscia O_DIRECT. Podsumowujac, O_DIRECT jest narzedziem o potencjalnie duzych mozliwosciach, ktorego nalezy uzywac ze spora dawka ostroznosci. Zaleca sie, aby aplikacje korzystajace z O_DIRECT, traktowaly go jako, domyslnie wylaczona, opcje poprawiajaca wydajnosc. USTERKI Obecnie nie da sie wlaczyc wejscia/wyjscia sterowanego sygnalem podajac znacznik O_ASYNC przy wywolaniu open(); nalezy uzyc fcntl(2), aby wlaczyc ten znacznik. Przy probie okreslenia, czy jadro obsluguje funkcje O_TMPFILE, nalezy sprawdzac dwa rozne kody bledu: EISDIR i ENOENT. Jesli we flags poda sie O_CREAT oraz O_DIRECTORY, a plik podany w sciezce pathname nie istnieje, open() utworzy zwykly plik (tj. O_DIRECTORY zostanie zignorowany). ZOBACZ TAKZE 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) 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.9.1 2 maja 2024 r. open(2)