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
三、核心特性
- 共享文件表:
-
- 复制后的文件描述符与原描述符指向同一个打开文件表条目
- 共享文件偏移量、文件状态标志等信息
- 文件描述符编号:
-
dup()返回系统中最小的未使用文件描述符dup2()可以指定新的文件描述符编号
- 关闭行为:
-
- 如果
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 和复制是原子的 |
六、注意事项
- 关闭责任:复制后的文件描述符需要单独关闭,两者相互独立
- 共享偏移量:对一个描述符的读写会影响另一个的偏移量
- 错误处理:操作失败时需检查
errno - 特殊 FD:可以复制标准输入 (0)、标准输出 (1)、标准错误 (2)
- 文件锁:通过一个 FD 设置的锁对另一个 FD 同样有效
1849

被折叠的 条评论
为什么被折叠?



