close(2)

НАИМЕНОВАНИЕ
close - закрывает файловый дескриптор

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

ОБЗОР
#include <unistd.h>

int close(int fd);

ОПИСАНИЕ
Программа close() закрывает файловый дескриптор, так что он больше не ссылается ни на какой файл и может быть использован повторно. Любые блокировки записей (смотрите fcntl(2)), сохраненные в файле, с которым он был связан и которым владел процесс, удаляются независимо от файлового дескриптора, который использовался для получения блокировки. Это имеет некоторые печальные последствия и следует быть особенно осторожным при использовании рекомендуемой блокировки записей. Смотрите в fcntl(2) о рисках и последствиях, а также (вероятно, предпочтительных) блокировках дескрипторов открытых файлов.

Если fd является последним файловым дескриптором, ссылающимся на базовый дескриптор открытого файла (смотрите open(2), то ресурсы, связанные с дескриптором открытого файла, освобождаются; если файловый дескриптор был последней ссылкой на файл, удалённый с помощью unlink(2), то файл окончательно удаляется.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении программы close() возвращается 0. В случае ошибки возвращается -1, а значение errno указывает на ошибку.

ОШИБКИ

EBADF
    Значение fd не является допустимым дескриптором открытого файла.

EINTR
    Вызов close() был прерван по сигналу; смотрите signal(7).

EIO Произошла ошибка ввода-вывода.

ENOSPC
EDQUOT
    В NFS об этих ошибках, обычно, не сообщается при первой записи, которая превысила доступное пространство памяти, а только при последующих операциях write(), fsync(2) или close().

See CAVEATS for a discussion of why close() should not be retried after an error.

СТАНДАРТЫ
POSIX.1-2008.

ИСТОРИЯ
4.3BSD, SVr4, POSIX.1-1988.

ПРИМЕЧАНИЯ
Флаг файлового дескриптора close-on-exec можно использовать для гарантии того, что файловый дескриптор автоматически закроется при успешном выполнении execve(2). Смотрите подробности в fcntl(2).

CAVEATS
Выполнение закрытия без ошибок не гарантирует, что данные были успешно записаны на диск, так как в ядре используется буферный кэш для отложенных записей. Как правило, файловые системы не записывают буферы при закрытии файла. Если требуется гарантировать физическую запись на используемый диск, то можно использовать fsync(2) (дальше всё будет зависеть от аппаратурных особенностей диска).

  Многопоточные процессы и close()
Вероятно неблагоразумно закрывать дескрипторы файла, в то время как они могут использоваться системными вызовами других потоков того же процесса. Поскольку файловый дескриптор может использоваться повторно, то существуют некоторые неясные условия гонки, которые могут вызвать непреднамеренные побочные эффекты.

Кроме того, рассмотрим следующий сценарий, в котором два потока выполняют операции с одним и тем же файловым дескриптором:

(1) Один поток блокируется при системном вызове ввода-вывода для файлового дескриптора. Например, он пытается выполнить write(2) (запись) в канал, который уже заполнен, или пытается выполнить read(2) (чтение) из потокового сокета, в котором в данный момент нет доступных данных.

(2) Другой поток закрывает файловый дескриптор.

Поведение в этой ситуации различается в разных системах. В некоторых системах, когда файловый дескриптор закрыт, системный вызов блокировки немедленно возвращается с ошибкой.

В Linux (и, возможно, в некоторых других системах) поведение иное: системный вызов блокировки ввода-вывода содержит ссылку на дескриптор базового открытого файла и эта ссылка сохраняет дескриптор открытым до завершения системного вызова ввода-вывода (смотрите open(2) для обсуждения открытого файлового дескриптора). Таким образом, блокирующий системный вызов в первом потоке может успешно завершиться после close() во втором потоке.

  Обработка ошибки, возвращённой close()
Аккуратный программист всегда проверяет возвращаемое close() значение, так как очень вероятно, что об ошибках предыдущей операции write(2) будет сообщено только при последнем вызове close(), который освобождает дескриптор открытого файла. Невыполнение проверки возвращаемого значение при закрытии файла может привести к silent (неучтённой) потере данных. Это особенно часто встречается с NFS и с дисковыми квотами.

Однако заметим, что возвращаемая ошибка должна использоваться только для диагностики (т. е. предупреждать приложение, что, возможно, есть незаконченные операции ввода-вывода или произошла ошибка ввода-вывода) или для исправления (например, повторной записи файла, или для создания резервной копии).

Повторный вызов close() после получения ошибки делать не стоит, так как это может привести к закрытию повторно использованного файлового дескриптора другого потока. Это может произойти из-за того, что ядро Linux always освобождает файловый дескриптор в самом начале операции закрытия, делая его доступным для повторного использования. Шаги, которые могут вернуть ошибку, такие как сброс данных в файловую систему или в устройство, происходят только после операции закрытия.

Many other implementations similarly always close the file descriptor (except in the case of EBADF, meaning that the file descriptor was invalid) even if they subsequently report an error on return from close(). POSIX.1-2008 was silent on this point.

Аккуратный программист, который хочет узнать об ошибках ввода-вывода, перед вызовом close() вызовет fsync(2).

The EINTR error is a somewhat special case. Regarding the EINTR error, POSIX.1-2008 said:

    If close() is interrupted by a signal that is to be caught, it shall return -1 with errno set to EINTR and the state of fd is unspecified.

This permits the behavior that occurs on Linux and many other implementations, where, as with other errors that may be reported by close(), the file descriptor is guaranteed to be closed. However, it also permits another possibility: that the implementation returns an EINTR error and keeps the file descriptor open. (According to its documentation, HP-UX's close() does this.) The caller must then once more use close() to close the file descriptor, to avoid file descriptor leaks. This divergence in implementation behaviors provides a difficult hurdle for portable applications, since on many implementations, close() must not be called again after an EINTR error, and on at least one, close() must be called again.

POSIX.1-2024 standardized the behavior of HP-UX, making Linux and many other implementations non-conforming. There are no plans to change the behavior on Linux.

СМОТРИТЕ ТАКЖЕ
close_range(2), fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) Dmitry Bolkhovskikh <d20052005@yandex.ru>, Yuri Kozlov <yuray@komyakino.ru> и Aleksandr Felda <isk8da@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).