Linux- dup()系统调用

dup()

dup()(duplicate)是一个UNIX系统调用,用于创建一个现有文件描述符的副本。这个新的文件描述符与原始文件描述符在许多方面是相同的:它们共享同一个文件表项,这意味着它们指向相同的文件、套接字或其他I/O通道,并共享相同的文件偏移量、访问权限等。

函数原型

dup()函数的原型如下:

#include <unistd.h>

int dup(int oldfd);

其中,oldfd是要复制的现有文件描述符。

返回值

成功时,返回新的文件描述符;失败时,返回-1。

具体行为

  1. 最小可用描述符dup()会返回当前可用的最小整数值作为新的文件描述符。
  2. 文件状态标志:新的文件描述符会有自己独立的一组文件状态标志(FD_CLOEXEC等),但它会共享所有其他的状态,包括文件偏移量和访问模式(读、写、读写)。
  3. 共享锁和其他状态:由于新旧文件描述符共享同一文件表项,所以文件锁、操作模式、文件偏移量等也是共享的。

示例

dup()经常用于重定向标准输入、输出和错误流。例如,在一个进程中,我们可能想把标准输出(通常是文件描述符1)重定向到一个文件。这可以通过以下步骤完成:

  1. 使用open()打开一个文件,获取其文件描述符。
  2. 使用dup()来复制这个文件描述符,并覆盖标准输出的文件描述符。

可以用close()dup()组合或者使用dup2()函数两种方式来操作。

方式一

使用close()dup()组合来进行I/O重定向是一种更底层和直接的方式。下面是一个简单的示例,演示如何将标准输出(文件描述符1)重定向到一个文件:

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

int main() {
    // 打开一个文件
    int fd = open("output.txt", O_WRONLY | O_CREAT, 0666);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    // 关闭标准输出(文件描述符1)
    close(1);

    // 使用dup复制fd,这将返回最低可用的文件描述符,即刚刚关闭的1
    int newfd = dup(fd);

    if (newfd < 0) {
        perror("dup");
        return 1;
    }

    // 此时,printf的输出将写入到"output.txt"
    printf("Hello, world!\n");

    // 关闭文件描述符
    close(fd);

    return 0;
}

这里的步骤如下:

  1. 使用open()打开一个文件,获取一个文件描述符fd
  2. 使用close(1)关闭标准输出(文件描述符1)。
  3. 使用dup(fd)复制fd到最低可用的文件描述符上,因为标准输出(文件描述符1)刚被关闭,所以dup()会返回1作为新的文件描述符。

现在,由于标准输出(文件描述符1)已经被重定向到output.txt,所有写入到标准输出的数据(例如,通过printf())都将被写入到该文件中。

这种方法的优点是它直接和明确,但缺点是需要确保在调用dup()之前正确地关闭了目标文件描述符。这通常不是问题,但在更复杂的程序中可能会导致错误或不一致的行为。因此,许多程序更倾向于使用dup2(),因为它提供了一个更为安全和一致的方式来进行文件描述符的复制和替换。

方式二

下面是一个简单的示例,展示如何用dup2()将标准输出重定向到一个文件:

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

int main() {
    // 打开一个文件
    int fd = open("output.txt", O_WRONLY | O_CREAT, 0666);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    // 将标准输出(文件描述符1)重定向到fd指向的文件
    if (dup2(fd, 1) < 0) {
        perror("dup2");
        return 1;
    }

    // 此时,printf的输出将写入到"output.txt"
    printf("Hello, world!\n");

    // 关闭文件描述符
    close(fd);

    return 0;
}

在这个示例中,dup2(fd, 1)调用会关闭标准输出(如果它还未被关闭)并复制fd,使其成为新的标准输出。因此,当调用printf()或其他写入到标准输出的函数时,输出会被写入到"output.txt"文件中。

这里,dup2()确保了新的文件描述符(在本例中是标准输出,文件描述符为1)指向与旧的文件描述符(在本例中是fd)相同的文件或其他资源。所以,它提供了一种方便的方式来实现I/O重定向。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
下面是课程列表: ├day01-01 系统介绍之缓冲区刷新.mp4 ├day01-02 系统介绍之man手册的使用.mp4 ├day02_文件查找规则.mp4 ├day03-01 调试输出点.mp4 ├day03-02 改变结构体对齐规则.mp4 ├day03-03 零长数组.mp4 ├day04-01 错误输出.mp4 ├day04-02 文件操作.mp4 ├day05-01 系统调用之文件操作.mp4 ├day05-02 C库函数对文件操作.mp4 ├day06-01 获取文件访问标识、文件加锁.mp4 ├day06-02 文件的访问权限、文件权限操作.mp4 ├day07-01链接文件操作.mp4 ├day07-02 目录操作.mp4 ├day08-01获取文件目录属性.mp4 ├day08-02 获取当前工作目录.mp4 ├day09-01 临时文件.mp4 ├day09-02 获取系统环境变量.mp4 ├day10_环境变量的增、删、改、查.mp4 ├day11-01 创建屏蔽字.mp4 ├day11-02 知识小结.mp4 ├day12-01 dup文件描述符复制.mp4 ├day12-02 dup2 文件描述符复制.mp4 ├day13_Mmap与文件关联映射.mp4 ├day14-01 匿名模式.mp4 ├day14-02 缓冲区(行缓冲 全缓冲 无缓冲).mp4 ├day14-03 获取进程id.mp4 ├day15-01 获取fork子父进程id.mp4 ├day15-02 子父进程 执行顺序 资源共享 资源回收.mp4 ├day16-01 ufork之子父进程 执行顺序 资源共享 资源回收.mp4 ├day16-02 孤儿进程.mp4 ├day16-04 守护进程讲解.mp4 ├day17-01 守护进程实现.mp4 ├day18-01 fork与sighal的组合(避免僵尸进程).mp4 ├day18-02 匿名管道之创建、缓冲区大小、阻塞模式.mp4 ├day18-03 知识点总结.mp4 ├day19_匿名管道子父进程通信、有名管道创建、删除.mp4 ├day20_有名管道的特点、在子父进程及非子父进程间操作.mp4 ├day21-01 有名管道的创建、缓冲区大小、阻塞模式、信号.mp4 ├day21-02 有名管道进程间通信.mp4 ├day22_消息队列默认属性及改变方法.mp4 ├day23-01 消息队列、读写操作.mp4 ├day23-02 消息队列之mp-notify读操作.mp4 ├day23-03 消息队列之mp-tined-recv、mp-tined-sewd.mp4 ├day24-01 共享内存的读写操作.mp4 ├day24-02 共享内存与map的公用.mp4 ├day25-01 共享内存综合案例操作.mp4 ├day25-02 匿名信号量的讲解使用.mp4 ├day25-03 匿名信号量同步.mp4 ├day26-01巩固知识点回顾与总结.mp4 ├day26-02 匿名信号量的互斥.mp4 ├day26-03 线程id 线程比较.mp4 ├day27-01 线程的执行顺序 资源共享.mp4 ├day27-02 线程资源回收 线程变量创建 线程属性.mp4 ├day27-03 线程栈空间获取 线程中断.mp4 ├day28-01 线程及信号量组合同步、组合互斥.mp4

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫客36

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值