Linux close函数怎么用?linux关闭文件描述符方法

在 Linux 系统编程中,close() 是一个至关重要的系统调用,用于关闭一个打开的文件描述符(file descriptor)。

以下是关于 close() 函数的详细解析,包括原型、行为、返回值、常见陷阱以及最佳实践。

Linux系统编程:open/close函数详解
加载中
Linux系统编程:open/close函数详解

函数原型

#include <unistd.h>
int close(int fd);
  • 参数fd 是要关闭的文件描述符。
  • 返回值
    • 成功时返回 0
    • 失败时返回 -1,并设置 errno 以指示错误原因。

核心行为

当调用 close(fd) 时,内核执行以下操作:

  1. 引用计数检查

    • 每个打开的文件描述符在内核中都有一个引用计数。
    • 如果该描述符是通过 dup()fork() 共享的,关闭它只会减少引用计数,不会立即释放底层资源。
    • 只有当引用计数降为 0 时,内核才会真正释放该文件描述符占用的资源(如文件偏移量、打开文件状态标志等)。
  2. 释放资源

    • 如果引用计数为 0,内核会:
      • 释放文件描述符槽位(使其可被新打开的文件复用)。
      • 如果这是最后一个指向该打开文件表项的描述符,内核会执行

        Linux close函数怎么用?linux关闭文件描述符方法

        关闭操作(如刷新缓冲区、通知文件系统更新 inode 等)。

  3. 标准文件描述符

    • close(0) 关闭标准输入(stdin)。
    • close(1) 关闭标准输出(stdout)。
    • close(2) 关闭标准错误(stderr)。
    • 关闭这些描述符后,后续的 I/O 操作可能会失败或行为未定义,除非重新打开它们。

常见错误与 errno

错误码 含义 常见原因
EBADF 文件描述符无效 fd 不是有效的打开文件描述符(可能已关闭、从未打开或值非法)
EINTR 系统调用被信号中断 关闭操作被信号中断(罕见,但需处理)
EIO I/O 错误 底层文件系统或设备发生错误

最佳实践与注意事项

✅ 始终检查返回值

if (close(fd) == -1) {
    perror("close failed");
    // 根据程序逻辑决定是否退出或继续
}

✅ 关闭后不再使用

  • 关闭文件描述符后,不要再对该 fd 进行任何操作(如

    Linux close函数怎么用?linux关闭文件描述符方法

    read, write, lseek),否则会导致 EBADF 错误。

  • 建议将 fd 设为 -1 作为标记:
    close(fd);fd = -1; // 防止误用

✅ 处理 EINTR

虽然 close() 很少被信号中断,但在编写健壮代码时,应处理 EINTR

while (close(fd) == -1 && errno == EINTR) {
    // 被信号中断,重试
}
if (errno != 0) {
    perror("close failed");
}

✅ 与 dup()fork() 的关系

  • fd 是通过 dup(fd) 创建的,关闭其中一个副本不会影响另一个副本对底层文件的访问。
  • fork() 之后,子进程继承父进程的文件描述符,关闭父进程中的 fd 不会影响子进程中的副本,反之亦然。

✅ 资源泄漏

  • 忘记关闭文件描述符会导致资源泄漏(文件描述符耗尽、内存泄漏等)。
  • 在长时间运行的服务中,这可能导致程序崩溃或拒绝服务。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main() {
    int fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
       

Linux close函数怎么用?linux关闭文件描述符方法

perror("open failed"); return 1; } // 使用 fd 进行 read/write 操作... // 关闭文件描述符 if (close(fd) == -1) { perror("close failed"); return 1; } // 防止误用 fd = -1; printf("File closed successfully.n"); return 0; }

常见问题 FAQ

Q: close() 会删除文件吗?
A: 不会close() 只是关闭文件描述符,释放内核资源,要删除文件,应使用 unlink() 系统调用。

Q: 关闭标准输出(close(1))后,printf 还能用吗?
A: 不能printf 默认写入标准输出(fd 1),关闭后,printf 会失败或行为未定义,如果需要重定向输出,应先使用 dup2() 将新文件描述符复制到 fd 1。

Q: 如何确保文件数据已写入磁盘?
A: close() 会触发内核将缓冲区中的数据刷新到磁盘(通过 fsync() 机制),但不能保证物理磁盘已写入,如需强一致性,应在 close() 前调用 fsync(fd)


close() 是 Linux 文件 I/O 的基础操作,正确管理文件描述符的生命周期(打开 → 使用 → 关闭)是编写稳定、安全 C 程序的关键,务必检查返回值、处理错误,并避免资源泄漏。

首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/477760.html

(0)
什么是floorplan?floorplan和户型图有什么区别
上一篇 2026年7月10日 02:57
heatmapmin.js是什么?heatmap.min.js怎么用
下一篇 2026年7月10日 02:58

相关推荐

  • linux shell乱码怎么解决?linux终端中文显示乱码

    Linux Shell出现乱码的核心原因是终端编码、系统环境变量与文件实际编码不一致,最直接的解决方式是将LANG和LC_ALL环境变量统一设置为UTF-8,当你面对满屏的问号或方块时,不要惊慌,这通常不是系统崩溃,而是字符集在“翻译”过程中出了岔子,Linux系统本身并不强制规定某种编码,它只是忠实地存储字节……

    2026年7月7日
    2100
  • Linux任务队列怎么实现?Linux任务队列原理详解

    在 Linux 系统中,“任务队列”并不是一个单一的软件,而是指多种用于管理、调度和执行后台任务(Job)的机制,根据任务的性质(一次性执行、周期性执行、高优先级等),Linux 提供了不同的工具来处理任务队列,以下是 Linux 中主要的任务队列机制及其应用场景:cron:周期性任务队列用途:用于定期执行任务……

    2026年7月12日
    7700
  • Linux如何保留端口?linux保留端口号配置方法

    在 Linux 中,“保留端口”通常指的是防止其他程序占用某些特定端口,或者确保某些端口始终可用给特定的服务,这可以通过以下几种方式实现:使用 systemd 服务管理端口如果你运行的是一个 systemd 服务(如 Nginx、MySQL 等),可以通过配置服务文件来绑定特定端口,示例:Nginx 绑定 80……

    2026年7月10日
    18700
  • Linux堆栈空间不足怎么解决?linux堆栈溢出怎么排查

    Linux堆栈空间是进程执行函数调用时用于存储局部变量、函数参数和返回地址的内存区域,其默认大小通常受限于系统限制,可通过ulimit命令查看或调整,过大易导致栈溢出崩溃,过小则限制深层递归能力,理解Linux堆栈空间,首先要把它想象成一个垂直堆叠的箱子,每个函数调用就像往箱子里放一个新的盒子,函数结束则取出盒……

    2026年7月12日
    15400
  • Linux怎么安装WinRAR?在Linux系统下如何解压rar文件

    Linux系统原生不支持WinRAR,需通过安装RARLAB官方提供的命令行工具RAR或开源替代品Unrar来实现对WinRAR格式文件的解压与压缩,且通常建议优先使用开源方案以规避版权风险,在Linux生态中,提到WinRAR往往会产生一种认知错位,WinRAR是Windows平台下的经典压缩软件,拥有极高的……

    2026年7月7日
    13500
  • linux内核变化有哪些?linux内核版本更新详解

    Linux内核的每一次迭代都在重塑云计算与边缘计算的底层逻辑,2026年的核心趋势聚焦于eBPF技术的深度集成、实时性优化以及针对AI负载的专用调度器改进,Linux内核演进的核心驱动力与架构变革近年来,Linux内核不再仅仅是操作系统的核心,它正演变为云原生时代的“超级抽象层”,业内专家指出,内核层面的变化直……

    2026年7月8日
    13500
  • linux root uid是什么?linux系统root用户uid是多少

    Linux系统中的root用户UID固定为0,这是内核识别最高权限账户的唯一标识,任何UID为0的账户均拥有系统最高控制权,在Linux的权限管理体系中,UID(User ID)是系统区分用户身份的核心机制,对于大多数普通用户而言,UID从1000开始递增,而root用户作为系统的“超级管理员”,其UID被硬编……

    2026年7月9日
    5800
  • Linux如何编辑xml文件?linux编辑xml内容的方法

    在 Linux 系统中编辑 XML 文件,通常有以下几种常用方法,根据你的需求(是简单修改、批量处理还是复杂格式化)可以选择不同的工具:使用命令行编辑器(最常用)Vim / ViVim 是 Linux 上最强大的文本编辑器之一,支持语法高亮和自动缩进,安装(如果未安装):sudo apt install vim……

    2026年7月10日
    19500
  • Linux Socket连接断开怎么办?如何排查网络异常

    Linux Socket断开通常由对端发送FIN包、网络中断、超时未心跳或进程异常退出触发,排查需结合ss -t查看状态、dmesg查内核日志及应用层错误码,在网络通信中,Socket连接就像两条城市间的电话线,当一方挂断或线路被剪断,连接就会终止,对于开发者而言,理解这一过程并非为了背诵RFC文档,而是为了在……

    2026年7月5日
    14100
  • Linux如何安装OpenMP?Linux安装OpenMP详细步骤

    在Linux系统中安装OpenMP,最直接且通用的方法是安装GCC编译器套件,因为OpenMP是GCC内置支持的并行编程标准,无需额外下载独立库文件,许多开发者在初次接触并行计算时,往往被复杂的依赖关系劝退,OpenMP并非一个需要单独下载的独立软件包,而是一种编译器指令集,只要你的Linux发行版配备了支持O……

    2026年7月6日
    8000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(1条)

  • 陈红
    陈红 2026年7月10日 16:35

    三点睡不着…这文章挺硬核。不过close了fd最好检查下返回值啊,不然资源泄漏了半夜找bug真的会谢…困死