close(2) System Calls Manual close(2)

close - zamyka deskryptor pliku

Standardowa biblioteka C (libc, -lc)

#include <unistd.h>
int close(int fd);

close() zamyka deskryptor pliku, tak że nie odnosi się on już później do żadnego pliku i może być użyty ponownie. Wszelkie blokady na poziomie rekordu (zob. fcntl(2)) utrzymywane na pliku, z którymi deskryptor był związany, i których właścicielem był proces, zostają usunięte, niezależnie od deskryptora plików, którego użyto dla uzyskanie blokady. Ma to pewne niefortunne skutki, dlatego należy być szczególnie ostrożnym przy używaniu pomocniczego zakładania blokad na poziomie rekordów. W podręczniku fcntl(2) opisano ryzyka i konsekwencje oraz (prawdopodobnie preferowane) blokady opisu otwartego pliku (ang. open file description (OFD) lock).

Jeśli fd jest ostatnim deskryptorem pliku odnoszącego się do podległego opisu otwartego pliku (OFD, zob. open(2)), to zasoby związane z opisem otwartego pliku zostają zwolnione; jeśli deskryptor pliku był ostatnim odniesieniem do pliku, który usunięto za pomocą polecenia unlink(2), to plik jest kasowany.

close() w przypadku powodzenia zwraca zero. W razie wystąpienia błędu zwracane jest -1 i ustawiana jest zmienna errno wskazując na błąd.

fd nie jest prawidłowym deskryptorem otwartego pliku.
Funkcja close() została przerwana przez sygnał; zobacz signal(7).
Wystąpił błąd wejścia/wyjścia.
W NFS, błędy te nie są zwykle zgłaszane wobec wobec pierwszego zapisu, który przekroczył dostępną przestrzeń dyskową, lecz wobec kolejnego write(2), fsync(2) lub close().

Zob. UWAGI, aby dowiedzieć się dlaczego close() nie powinien być powtarzany po wystąpieniu błędu.

POSIX.1-2008.

POSIX.1-2001, SVr4, 4.3BSD.

Pomyślne zamknięcie nie gwarantuje, że dane zostaną pomyślnie zapisane na dysku, gdyż jądro używa bufora do opóźnienia zapisów. Zwykle systemy plików nie opróżniają buforów przy zamykaniu pliku. Jeśli istnieje potrzeba zapewnienia, aby dane zostały zapisane fizycznie na nośniku, należy użyć fsync(2) (zapis zależy w tym momencie od właściwości sprzętowych dysku).

Znacznik deskryptora pliku zamknij-przy-wykonaniu może być użyty do upewnienia się, że dany deskryptor pliku jest automatycznie zamknięty po pomyślnym execve(2); więcej szczegółów w podręczniku fcntl(2).

Prawdopodobnie nie jest roztropnie zamykać deskryptory pliku w chwili, gdy mogą być one używane przez wywołania systemowe w innych wątkach tego samego procesu. Ponieważ deskryptora pliku można użyć ponownie, istnieją pewne zawiłe sytuacje hazardu, które mogą przynieść pewnie nieprzewidziane skutku uboczne.

Co więcej, proszę rozważyć następujący scenariusz, gdy dwa wątki przeprowadzają operacje na tym samym deskryptorze pliku:

(1)
Jeden wątek jest zablokowany w wywołaniu wejścia/wyjścia na deskryptorze pliku. Może to być na przykład próba write(2) do zapełnionego potoku lub próba read(2) z gniazda strumieniowego, które aktualnie nie dysponuje danymi.
(2)
Inny wątek zamyka deskryptor pliku.

Zachowanie w takiej sytuacji różni się w różnych systemach. W niektórych, po zamknięciu deskryptora pliku, blokujące wywołanie systemowe natychmiast powróci z błędem.

W Linuksie (i prawdopodobnie w niektórych innych systemach) zachowanie jest inne: blokujące wywołanie systemowe wejścia/wyjścia utrzymuje referencję do podległego opisu otwartego pliku (OFD) i to odniesienie utrzymuje opis otwarty do momentu zakończenia wywołania systemowego wejścia/wyjścia (zob. open(2) aby dowiedzieć się więcej o opisach otwartego pliku). Z tego względu, blokujące wywołanie systemowe w pierwszym wątku może się pomyślnie zakończyć po close() w drugim wątku.

Ostrożny programista sprawdzi wartość zwracaną przez close(), ponieważ może się zdarzyć, że błędy wcześniejszej operacji write(2) zostaną zgłoszone jedynie przy kończącym close(), zwalniającym opis otwartego pliku (OFD). Niesprawdzenie zwróconej podczas zamykania pliku wartości może doprowadzić do niesygnalizowanej utraty danych. Jest to obserwowane zwłaszcza w przypadku NFS i przy używaniu przydziałów dyskowych.

Proszę jednak zauważyć, że zwrócenie błędu powinno być używane jedynie do celów diagnostycznych (tj. jako ostrzeżenie dla aplikacji, że wciąż może istnieć oczekujące wejście/wyjście lub wejście/wyjście mogło się nie powieść) lub do celów zaradczych (np. ponowny zapis pliku lub utworzenie kopii).

Ponowna próba wykonania close() po zwróceniu błędu nie jest właściwym zachowaniem, ponieważ może to spowodować zamknięcie użytego ponownie deskryptora pliku z innego wątku. Może się tak zdarzyć, ponieważ jądro Linux zawsze uwalnia deskryptor plików wcześnie przy operacji zamykania, zwalniając go do ponownego użytku; kroki mogące zwrócić błąd, takie jak opróżnianie danych do systemu plików lub urządzenia, mogą wystąpić przy operacji zamykania jedynie później.

Większość innych implementacji zachowuje się podobnie zamykając deskryptor plików zawsze (z wyjątkiem EBADF oznaczającego, że deskryptor pliku był nieprawidłowy) nawet, gdy następnie zwrócą błąd przy powrocie z close(). POSIX.1 nie wypowiada się obecnie na ten temat, ale istnieją plany nakazania tego zachowania w następnym głównym wydaniu standardu

Ostrożny programista, chcący posiąść informacje o błędach wejścia/wyjścia, może poprzedzić close() wywołaniem do fsync(2).

Błąd EINTR jest poniekąd szczególnym przypadkiem. Odnośnie błędu EINTR norma POSIX.1-2008 wspomina:

Jeśli close() zostanie przerwane mającym być przechwyconym sygnałem, ma zwrócić wartość -1 z errno ustawionym na EINTR, a stan fildes jest nieokreślony.

Zezwala to na zachowanie występujące w Linuksie i wielu innych implementacjach, gdzie, jak w przypadku innych błędów, jakie może zwrócić close(), deskryptor pliku zostanie na pewno zamknięty. Istnieje jednak również inna możliwość: że implementacja zwróci błąd EINTR i utrzyma otwarty deskryptor pliku (zgodnie z dokumentacją HP-UX, jego close() tak czyni). Wywołujący musi wówczas użyć close() ponownie, aby zamknąć deskryptor pliku i aby uniknąć wycieku deskryptora pliku. Ta rozbieżność w implementacji czyni trudności przenośnym aplikacjom, ponieważ w wielu implementacjach close() nie musi być ponownie wywoływane po błędzie EINTR, a w przynajmniej jednej, close() musi być ponownie wywołane. Istnieją plany rozwiązania tej zagwozdki w następnym głównym wydaniu standardu POSIX.1.

close_range(2), fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)

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.

31 października 2023 r. Linux man-pages 6.06