close(2)

NAZWA
close - zamyka deskryptor pliku

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <unistd.h>

int close(int fd);

OPIS
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.

WARTOŚĆ ZWRACANA
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.

BŁĘDY

EBADF
    fd nie jest prawidłowym deskryptorem otwartego pliku.

EINTR
    Funkcja close() została przerwana przez sygnał; zobacz signal(7).

EIO Wystąpił błąd wejścia/wyjścia.

ENOSPC
EDQUOT
    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. ZASTRZEŻENIA, aby dowiedzieć się dlaczego close() nie powinien być powtarzany po wystąpieniu błędu.

STANDARDY
POSIX.1-2008.

HISTORIA
4.3BSD, SVr4, POSIX.1-1988.

UWAGI
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).

ZASTRZEŻENIA
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).

  Procesy wielowątkowe i close()
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.

  Zajmowanie się błędami zwróconymi przez close()
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-2008 nie wypowiadał się na ten temat.

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ła:

    Jeśli close() zostanie przerwane mającym być przechwyconym sygnałem, ma zwrócić wartość -1 z errno ustawionym na EINTR, a stan fd 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.

POSIX.1-2024 uczyniło standardowym zachowanie HP-UX, co spowodowało niezgodność Linuksa i wielu innych implementacji z normą. Nie ma planów modyfikacji opisanego zachowania w Linuksie.

ZOBACZ TAKŻE
close_range(2), fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: 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 (https://www.gnu.org/licenses/gpl-3.0.html) 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.