Linux C 中的 dup () 和 dup2 () 函数详解

Linux C 中的 dup () 和 dup2 () 函数详解

一、函数基本概念

dup()dup2() 是用于复制文件描述符的系统调用,主要用途是:

  • 让多个文件描述符指向同一个打开的文件
  • 实现输入输出重定向(如将标准输出重定向到文件)
  • 在进程间共享文件描述符

二、函数原型与参数

dup () 原型

#include <unistd.h>
int dup(int oldfd);
  • 功能:复制文件描述符 oldfd
  • 返回值:成功返回新的文件描述符,失败返回 -1

dup2 () 原型

#include <unistd.h>
int dup2(int oldfd, int newfd);
  • 功能:将 oldfd 复制到 newfd,即让 newfd 指向 oldfd 所指向的文件
  • 返回值:成功返回 newfd,失败返回 -1

三、核心特性

  1. 共享文件表
    • 复制后的文件描述符与原描述符指向同一个打开文件表条目
    • 共享文件偏移量、文件状态标志等信息
  1. 文件描述符编号
    • dup() 返回系统中最小的未使用文件描述符
    • dup2() 可以指定新的文件描述符编号
  1. 关闭行为
    • 如果 newfd 已打开,dup2() 会先关闭它
    • 如果 oldfd 无效,dup2() 不会关闭 newfd

四、使用示例

1. dup () 基本用法

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    // 复制文件描述符
    int fd2 = dup(fd);
    if (fd2 == -1) {
        perror("dup failed");
        close(fd);
        return 1;
    }

    printf("原fd: %d, 复制的fd: %d\n", fd, fd2);

    // 写入操作会影响同一个文件偏移量
    write(fd, "hello", 5);
    write(fd2, " world", 6);  // 会接着"hello"后面写入

    close(fd);
    close(fd2);  // 需要关闭两个描述符
    return 0;
}

2. dup2 () 实现重定向

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    // 打开日志文件
    int logfd = open("output.log", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (logfd == -1) {
        perror("open failed");
        return 1;
    }

    // 保存标准输出的文件描述符
    int stdout_fd = dup(STDOUT_FILENO);
    if (stdout_fd == -1) {
        perror("dup failed");
        close(logfd);
        return 1;
    }

    // 将标准输出重定向到日志文件
    if (dup2(logfd, STDOUT_FILENO) == -1) {
        perror("dup2 failed");
        close(logfd);
        close(stdout_fd);
        return 1;
    }

    // 现在printf会写入到日志文件
    printf("这段文字会被重定向到文件\n");
    fprintf(stderr, "这段文字仍然输出到终端\n");

    // 恢复标准输出
    dup2(stdout_fd, STDOUT_FILENO);
    
    // 关闭文件描述符
    close(logfd);
    close(stdout_fd);
    
    // 现在printf恢复正常
    printf("这段文字输出到终端\n");
    return 0;
}

3. dup2 () 的原子操作特性

// 安全地交换两个文件描述符
void swap_fds(int fd1, int fd2) {
    int temp = dup(fd1);
    dup2(fd2, fd1);
    dup2(temp, fd2);
    close(temp);
}

五、关键区别与选择

特性

dup()

dup2()

新 FD 编号

自动分配(最小可用)

手动指定

灵活性

重定向用途

不适合

适合

原子性

无特殊保证

关闭旧 FD 和复制是原子的

六、注意事项

  1. 关闭责任:复制后的文件描述符需要单独关闭,两者相互独立
  2. 共享偏移量:对一个描述符的读写会影响另一个的偏移量
  3. 错误处理:操作失败时需检查 errno
  4. 特殊 FD:可以复制标准输入 (0)、标准输出 (1)、标准错误 (2)
  5. 文件锁:通过一个 FD 设置的锁对另一个 FD 同样有效
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值