Linux系统调用:深入理解 dup 和 dup2 的区别与用法

在 Linux 系统编程中,dup 和 dup2 是两个非常重要的系统调用,广泛应用于 标准输入/输出重定向、管道通信 和 文件描述符管理 等场景。本文将详细讲解这两个函数的区别、用法,并结合实际代码示例说明它们如何单独使用与配合使用。

一、基础知识:文件描述符(File Descriptor)

在 Unix/Linux 中,一切皆文件。文件、终端、套接字等 I/O 资源都用一个非负整数标识,这个整数就叫做文件描述符。
系统预定义了三个标准文件描述符:

名称文件描述符含义
stdin0标准输入
stdout1标准输出
stderr2标准错误输出

二、dup 和 dup2 的区别概览

项目dupdup2
作用复制文件描述符将一个文件描述符复制到指定的目标描述符
返回值最小可用的新文件描述符编号返回目标文件描述符
是否可指定目标否,只能自动选择是,第二个参数指定目标 fd
是否关闭原 fd是(如果目标 fd 已打开,会先关闭它)

三、dup 用法详解

函数原型

int dup(int oldfd);

功能

复制 oldfd 的文件描述符,返回一个新的描述符,它和 oldfd 指向相同的文件/设备,共享文件偏移量和状态。

示例:

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

int main() {
    int fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    int newfd = dup(fd);

    write(fd, "Hello ", 6);
    write(newfd, "World\n", 6);  // 实际写入文件的是 "Hello World"

    close(fd);
    close(newfd);
    return 0;
}

说明fd 和 newfd 都指向同一个文件,写入时共享文件偏移量,newfd 写入内容会继续跟在 fd 的后面。

四、dup2 用法详解

函数原型:

int dup2(int oldfd, int newfd);

功能:

将 oldfd 的复制内容复制到 newfd 上。如果 newfd 已打开,则先关闭它。最终 newfd 和 oldfd 指向相同的文件。

代码示例:

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

int main() {
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);

    dup2(fd, STDOUT_FILENO);  // 将 stdout 重定向到 log.txt

    printf("这条信息将写入文件 log.txt\n");

    close(fd);
    return 0;
}

说明:重定向后,printf 实际写入的是文件,而不是终端。

五、配合使用:备份和恢复输出流

在实际开发中,经常需要临时重定向输出到文件,然后再恢复原本的终端输出。这时我们可以配合使用 dup 和 dup2。

示例:将标准输出重定向到文件,再恢复

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

int main() {
    // 打开文件准备重定向
    int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) return 1;

    // 备份标准输出(终端)
    int saved_stdout = dup(STDOUT_FILENO);

    // 重定向 stdout 到文件
    dup2(fd, STDOUT_FILENO);

    printf("这行输出到文件 output.txt\n");

    // 恢复 stdout 到终端
    dup2(saved_stdout, STDOUT_FILENO);
    printf("这行输出回到了终端\n");

    close(fd);
    close(saved_stdout);
    return 0;
}

解释:
dup(STDOUT_FILENO):先备份标准输出(终端)。

dup2(fd, STDOUT_FILENO):重定向输出到文件。

dup2(saved_stdout, STDOUT_FILENO):再恢复回原来的终端输出。

六、总结

使用场景推荐用法
简单复制描述符dup
需要指定目标描述符dup2
临时重定向输出dup + dup2 配合使用

注意

dup 只负责复制,不关闭任何描述符。

dup2 在复制前会自动关闭目标 newfd,防止泄漏。

所有共享描述符共享文件偏移和状态,关闭任意一个不影响其他,但最后都应关闭以避免资源泄露。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值