linux-C/C++主子进程同时占用主进程文件描述符问题

在 Linux 系统中,当一个进程(A)打开文件并获取文件描述符(fd)后,如果通过 system() 启动子进程(B),子进程会继承父进程的所有打开文件描述符。这可能导致多个进程同时写入同一个日志文件,造成日志混乱或数据损坏。

书写辅助函数 set_fd_cloexec 为了解决这个问题。它通过设置 FD_CLOEXEC 标志位,确保在执行 exec 系列函数(如 system() 内部调用的 exec)时,文件描述符会被自动关闭,子进程不会继承该文件描述符。

函数解析

c 复制代码
static void set_fd_cloexec(int fd)
{
    if (fd < 0)  // 检查无效文件描述符
    {
        return;
    }
    int flags = fcntl(fd, F_GETFD);  // 获取当前文件描述符标志
    if (flags == -1)  // 检查获取是否失败
    {
        return;
    }
    fcntl(fd, F_SETFD, flags | FD_CLOEXEC);  // 设置 FD_CLOEXEC 标志
}

关键点说明

  1. FD_CLOEXEC 作用

    设置此标志后,当进程调用 exec 系列函数(如 system() 启动的子进程)时,操作系统会自动关闭该文件描述符,防止子进程继承。

  2. 函数逻辑

    • 先检查 fd 是否有效(fd >= 0
    • 使用 fcntl(fd, F_GETFD) 获取当前标志
    • 通过位或操作 flags | FD_CLOEXEC 添加标志
    • fcntl(fd, F_SETFD, ...) 应用新标志
  3. 使用场景

    在打开文件后立即调用此函数:

    c 复制代码
    int log_fd = open("app.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
    if (log_fd >= 0) {
        set_fd_cloexec(log_fd);  // 确保子进程不继承此 fd
    }

注意事项

  1. 错误处理

    当前函数忽略了 fcntl 的失败情况,实际应用中建议添加错误日志:

    c 复制代码
    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
        perror("fcntl(F_SETFD) failed");
    }
  2. 替代方案

    • 在打开文件时直接设置标志(更推荐):

      c 复制代码
      int fd = open("file.txt", O_RDWR | O_CLOEXEC, 0644);
    • Linux 专有函数:

      c 复制代码
      int fd = open("file.txt", O_RDWR | O_CLOEXEC, 0644);
  3. 继承例外

    若需要特定文件描述符被子进程继承(如标准输入/输出),则不应设置 FD_CLOEXEC

总结

通过正确设置 FD_CLOEXEC 标志,可确保:

  • 父进程(A)正常使用文件描述符
  • 子进程(B)启动时自动关闭该描述符
  • 避免多进程同时写文件导致的冲突
相关推荐
kyle~几秒前
导航---Small-GICP重定位算法
c++·机器人·ros2·导航
WBluuue9 分钟前
AtCoder Beginner Contest 451(ABCDEFG)
c++·算法
biubiubiu070611 分钟前
Linux 与 Shell 自动化运维基础知识记录
linux·运维·自动化
CoderCodingNo14 分钟前
【GESP】C++五级练习题 luogu-P1102 A-B 数对
开发语言·c++·算法
cpp_250125 分钟前
B3873 [GESP202309 六级] 小杨买饮料
数据结构·c++·算法·动态规划·题解·洛谷
2301_7890156228 分钟前
C++11新增特性:可变参数模板、lambda表达式、function包装器、bind绑定、defult和delete
c语言·开发语言·c++·算法·c++11·万能引用
默|笙31 分钟前
【Linux】进程概念与控制(2)_进程控制
java·linux·策略模式
代码AC不AC40 分钟前
【Linux】关于 mmap 文件映射
linux·mmap 文件映射
me83240 分钟前
【Linux】解决Docker-Compose拉取Jenkins时失败问题。
linux·docker·jenkins
tankeven1 小时前
HJ158 挡住洪水
c++·算法