CLOSE - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
close-关闭文件描述符
语法
#include <unistd.h> int close(int fd);
说明
close()关闭文件描述符,以便它不再引用任何文件,并且可以重用。与该进程关联并由该进程拥有的文件上保留的所有记录锁定(请参阅fcntl(2))(无论用于获取该锁定的文件描述符如何)都将被删除。
如果fd是引用基础打开文件描述的最后一个文件描述符(请参见open(2)),则释放与打开文件描述相关的资源;如果文件描述符是对使用unlink(2)删除的文件的最后引用,则该文件将被删除。
返回值
如果成功,close()返回零。如果出错,则返回-1,并正确设置errno。
错误说明
- EBADF
- fd不是有效的打开文件描述符。
- EINTR
- close()调用被信号中断;参见signal(7)。
- EIO
- 发生I / O错误。
- ENOSPC, EDQUOT
- 在NFS上,通常不会针对超出可用存储空间的第一个写入报告这些错误,而是针对随后的write(2),fsync(2)或close()报告这些错误。
请参阅注释,以获取有关为什么错误后不应重试close()的讨论。
遵循规范
POSIX.1-2001,POSIX.1-2008,SVr4、4.3BSD。
备注
成功关闭并不能保证数据已成功保存到磁盘,因为内核使用缓冲区高速缓存来推迟写入。通常,关闭文件时,文件系统不会刷新缓冲区。如果需要确保数据实际存储在基础磁盘上,请使用fsync(2)。 (这将取决于磁盘硬件。)
close-on-exec文件描述符标志可用于确保成功执行execve(2)时自动关闭文件描述符。有关详细信息,请参见fcntl(2)。
Multithreaded processes and close()
当文件描述符在同一进程中的其他线程中被系统调用使用时,关闭文件描述符可能是不明智的。由于文件描述符可能会被重用,因此有些模糊的竞争条件可能会导致意外的副作用。
此外,请考虑以下情形,其中两个线程正在同一文件描述符上执行操作:
- 1.
- 在文件描述符的I / O系统调用中阻塞了一个线程。例如,它正在尝试将(2)写入已满的管道,或者试图从当前没有可用数据的流套接字读取(2)。
- 2.
- 另一个线程关闭文件描述符。
在这种情况下,行为在不同系统之间会有所不同。在某些系统上,当文件描述符关闭时,阻塞的系统调用将立即返回错误。
在Linux(可能还有其他一些系统)上,行为是不同的。阻塞的I / O系统调用将保留对基础打开文件描述的引用,并且该引用将使描述保持打开状态,直到I / O系统调用完成。 (有关打开文件描述的讨论,请参见open(2)。)因此,第一个线程中的阻塞系统调用可能在第二个线程中的close()之后成功完成。
Dealing with error returns from close()
仔细的程序员将检查close()的返回值,因为很有可能仅在释放打开文件描述的最终close()上报告先前write(2)操作的错误。关闭文件时未检查返回值可能会导致数据无提示丢失。使用NFS和磁盘配额尤其可以观察到这一点。
但是请注意,故障返回仅应用于诊断目的(即,警告应用程序可能仍存在I / O挂起或I / O可能已失败)或补救目的(例如,编写再次创建文件或创建备份)。
在失败返回之后重试close()是错误的事情,因为这可能导致另一个线程的重用文件描述符被关闭。发生这种情况是因为Linux内核总是在关闭操作的早期释放文件描述符,将其释放以供重用。仅在稍后的关闭操作中才会发生可能返回错误的步骤,例如将数据刷新到文件系统或设备。
同样,许多其他实现总是关闭文件描述符(除了EBADF以外,这意味着文件描述符无效),即使它们随后在从close()返回时报告错误。 POSIX.1目前在这一点上保持沉默,但是计划在标准的下一个主要版本中强制要求这种行为。
一位想了解I / O错误的细心程序员可以在close()之前调用fsync(2)。
EINTR错误是一种特殊情况。关于EINTR错误,POSIX.1-2008说:
- 如果close()被要捕获的信号中断,则它将返回-1,并将errno设置为EINTR,并且未指定fildes的状态。
这允许出现在Linux和许多其他实现上的行为,其中与close()可能报告的其他错误一样,保证文件描述符是关闭的。但是,它也允许另一种可能性:该实现返回EINTR错误并保持文件描述符为打开状态。 (根据其文档,HP-UX的close()执行此操作。)然后,调用方必须再次使用close()关闭文件描述符,以避免文件描述符泄漏。实现行为上的这种差异为便携式应用程序提供了一个困难的障碍,因为在许多实现中,在EINTR错误之后一定不能再次调用close(),而在至少一个实现上,必须再次调用close()。计划解决POSIX.1标准的下一个主要版本的难题。
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。