Linux应用编程之dup函数和dup2函数

article/2025/10/1 11:23:52
Linux 系统中, open 返回得到的文件描述符 fd 可以进行复制,复制成功之后可以得到一个新文件描述符,使用新的文件描述符和旧的文件描述符都可以对文件进行 IO 操作,复制得到的文件描述符和旧的文件描述符拥有相同的权限,譬如使用旧的文件描述符对文件有读写权限,那么新的文件描述符同样也具 有读写权限;在 Linux 系统下,可以使用 dup dup2 这两个系统调用对文件描述符进行复制。我们来学习下两个函数的用法以及它们之间的区别。
 
复制得到的文件描述符与旧的文件描述符都指向了同一个文件表,假设 fd1 为原文件描述符, fd2 为复制得到的文件描述符,如下图所示:

 
因为复制得到的文件描述符与旧的文件描述符指向的是同一个文件表,所以可知,这两个文件描述符的 属性是一样,譬如对文件的读写权限、文件状态标志、文件偏移量等,所以从这里也可知道“复制”的含义实则是复制文件表。同样,在使用完毕之后也需要使用 close 来关闭文件描述符。
1、dup函数
dup 函数用于复制文件描述符
#include <unistd.h>
int dup(int oldfd);
oldfd 需要被复制的文件描述符。
返回值: 成功时将返回一个新的文件描述符,由操作系统分配,分配置原则遵循文件描述符分配原则; 如果复制失败将返回-1 ,并且会设置 errno 值。

 
复制得到的文件描述符与原文件描述符都指向同一个文件表,所以它们的文件读写偏移量是一样的,我们可以在不使用O_APPEND标志的情况下,通过文件描述符复制来实现文件的接续写。

示例代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(void)
{unsigned char buffer1[4], buffer2[4];int fd1, fd2;int ret;int i;/* 创建新文件 test_file 并打开 */fd1 = open("./test_file", O_RDWR | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);if (-1 == fd1){perror("open error");exit(-1);}/* 复制文件描述符 */fd2 = dup(fd1);if (-1 == fd2){perror("dup error");ret = -1;goto err1;}printf("fd1: %d\nfd2: %d\n", fd1, fd2);/* buffer 数据初始化 */buffer1[0] = 0x11;buffer1[1] = 0x22;buffer1[2] = 0x33;buffer1[3] = 0x44;buffer2[0] = 0xAA;buffer2[1] = 0xBB;buffer2[2] = 0xCC;buffer2[3] = 0xDD;/* 循环写入数据 */for (i = 0; i < 4; i++){ret = write(fd1, buffer1, sizeof(buffer1));if (-1 == ret){perror("write error");goto err2;}ret = write(fd2, buffer2, sizeof(buffer2));if (-1 == ret){perror("write error");goto err2;}}/* 将读写位置偏移量移动到文件头 */ret = lseek(fd1, 0, SEEK_SET);if (-1 == ret){perror("lseek error");goto err2;}/* 读取数据 */for (i = 0; i < 8; i++){ret = read(fd1, buffer1, sizeof(buffer1));if (-1 == ret){perror("read error");goto err2;}printf("%x%x%x%x", buffer1[0], buffer1[1],buffer1[2], buffer1[3]);}printf("\n");ret = 0;
err2:close(fd2);
err1:/* 关闭文件 */close(fd1);exit(ret);
}
测试代码中,我们使用了 dup 系统调用复制了文件描述符 fd1 ,得到另一个新的文件描述符 fd2 ,分别 通过 fd1 fd2 对文件进行写操作,最后读取写入的数据来判断是分别写还是接续写。


编译测试:

 

由打印信息可知, fd1 等于 3 ,复制得到的新的文件描述符为 5 ,打印出来的数据 显示为接续写,所以可知,通过复制文件描述符可以实现接续写。
2、dup2 函数
dup 系统调用分配的文件描述符是由系统分配的,遵循文件描述符分配原则,并不能自己指定一个文件 描述符,这是 dup 系统调用的一个缺陷;而 dup2 系统调用修复了这个缺陷,可以手动指定文件描述符,而不需要遵循文件描述符分配原则。
#include <unistd.h>
int dup2(int oldfd, int newfd);
oldfd 需要被复制的文件描述符。
newfd 指定一个文件描述符(需要指定一个当前进程没有使用到的文件描述符)。
返回值: 成功时将返回一个新的文件描述符,也就是手动指定的文件描述符 newfd ;如果复制失败将返 回-1 ,并且会设置 errno 值。
示例程序:
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(void)
{unsigned char buffer1[4], buffer2[4];int fd1, fd2;int ret;int i;/* 创建新文件 test_file 并打开 */fd1 = open("./test_file", O_RDWR | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);if (-1 == fd1){perror("open error");exit(-1);}/* 复制文件描述符 */fd2 = dup2(fd1, 100);if (-1 == fd2){perror("dup error");ret = -1;goto err1;}printf("fd1: %d\nfd2: %d\n", fd1, fd2);ret = 0;close(fd2);err1:/* 关闭文件 */close(fd1);exit(ret);
}
测试代码使用 dup2 函数复制文件描述符 fd1 ,指定新的文件描述符为 100 ,复制成功之后将其打印出来,

编译测试:

由打印信息可知,复制得到的文件描述符 fd2 等于 100,正是我们在 dup2 函数中指定的文件描述符。

文件描述符并不是只能复制一次,可以对同一个文件描述符 fd 调用 dup dup2 函数复制多次,得到多个不同的文件描述符。

http://chatgpt.dhexx.cn/article/5DwLqmgn.shtml

相关文章

linux文件重定向 dup,linux之dup和dup2函数解析

linux之dup和dup2函数解析 linux之dup和dup2函数解析 系统调用dup和dup2能够复制文件描述符。dup返回新的文件文件描述符(没有用的文件描述符最小的编号)。dup2可以让用户指定返回的文件描述符的值&#xff0c;如果需要&#xff0c;则首先接近newfd的值&#xff0c;他通常用来重…

dup和dup2函数

dup和dup2函数 dup和dup2用于复制文件描述符&#xff0c;通常用于重定向。 #include <unistd.h>int dup(int oldfd); int dup2(int oldfd, int newfd);dup函数创建一个新的文件描述符&#xff0c;该新文件描述符和原有文件描述符oldfd指向相同的文件、管道或者网络连接…

重定向(dup、dup2、dup3)--Linux

文章目录 &#x1f6a9;重定向是什么&#xff1f;&#x1f6a9;dup系列函数实现重定向&#x1f341;dup&#x1f341;dup2&#x1f341;dup3 &#x1f6a9;总结 &#x1f6a9;重定向是什么&#xff1f; 在上篇博客[文件描述符]中我曾提到了一个有意思的证明&#xff1a;进程在…

协议篇————3、DUP协议详解

一、UDP协议简介 UDP是OSI模型中一种无连接的传输层协议&#xff0c;它主要用于不要求分组顺序到达的传输中&#xff0c;分组传输顺序的检查与排序由应用层完成&#xff0c;提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是 IP协议与上层协议的接口。UDP协议适用端口分…

8086汇编语言dup指令学习

dup是duplicate的缩写&#xff0c;重复的意思&#xff1b; 用来定义重复的字节、字、双字、结构等内存缓冲区&#xff1b; db x dup()&#xff0c;x是重复的次数&#xff0c;&#xff08;&#xff09;里是要重复的数&#xff0c;逗号分隔&#xff1b; db 重复的次数 dup &…

文件描述符的复制(dup)

1.dup和dup2函数的介绍 int dup(int oldfd); 返回一个文件描述符&#xff0c;参数是要复制的那个文件描述符。2.使用dup进行文件描述符的复制 &#xff08;1&#xff09;dup系统调用对fd进行复制&#xff0c;会返回一个新的文件描述符&#xff0c;&#xff08;譬如原来的是3&a…

java面试题库app

java面试题库app是一款专为正在找工作的java程序员打造的软件&#xff0c;这款软件集合了精选的Java面试笔试题目及答案&#xff0c;致力于帮助用户通过面试和笔试&#xff0c;有需要的朋友快来下载吧。 java面试题库app特色 1、java基础(全面的java基础面试题&#xff0c;jav…

java-题库

java-题库 一、hashMap的底层实现1.1、hashMap概述1.2、JDK1.7-扩容源码1.3、JDK1.7链表迁移过程1.4、JDK1.8下的扩容机制 二、java面向对象的三大特征三、JVM相关四、集合相关五、JDK1.8新特性5.1、接口内可以添加非抽象的方法实现5.2、Lambda表达式5.3、函数式接口5.4、Strea…

Java二级考试题库

1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 14、 15、 16、 17、 18、 19、 20、 21、 22、 23、 24、 25、 26、 27、 注意&#xff1a;&#xff08;1&#xff09;基本型数据变量传递的是数值&#xff0c;修改会直接影响数据&#xff1b;而引用型变量传递的是…

java基础_题库详解

删除线格式 # 1 JDK和JRE有什么区别&#xff1f; JRE&#xff1a;Java Runtime Environment&#xff08; java 运行时环境&#xff09;。即java程序的运行时环境&#xff0c;包含了 java 虚拟机&#xff0c;java基础类库。 JDK&#xff1a;Java Development Kit&#xff08; ja…

Java笔试题

随机从1到100000中间随机取出100个不同的质数&#xff0c;然后按从小到大的顺序排列 public class IsPrime { //工具类// 输入一个数,判断是否为质数,费时方法public static Integer isPrime(int num) {if (num 0 || num 1)return -1;for (int i 2; i < num - 1; i) {if …

Java期末题库

根据如下图所示数据库信息&#xff0c;完成1-3小题。 &#xff08;1&#xff09;使用JDBC数据库连接技术&#xff0c;编写JDBCUtil工具类&#xff0c;在该类中定义getCon方法用于获得与数据库的连接对象&#xff0c;定义closeAll方法用于释放连接对象等资源。 import java.sql…

2022史上最全java面试题题库大全800题含答案

2022史上最全java面试题题库大全800题含答案 1、 meta标签的作用是什么 2、 ReenTrantLock可重入锁&#xff08;和synchronized的区别&#xff09;总结 3、 Spring中的自动装配有哪些限制&#xff1f; 4、 什么是可变参数&#xff1f; 5、 什么是领域模型(domain model)&#…

全国计算机等级考试——二级JAVA完整大题题库【五十三道】

全国计算机等级考试二级 JAVA 题目内容 编写于2023.04.10 分为40道选择题和3道大题&#xff08;大题是程序填空类型&#xff09; 其中选择题只能进去做一次&#xff0c;一旦退出来则不可再进&#xff08;注意&#xff01;&#xff09;。大题可以重复进入&#xff0c;重复做。…

java面试题题库大全800题

1、 meta标签的作用是什么 2、 ReenTrantLock可重入锁&#xff08;和synchronized的区别&#xff09;总结 3、 Spring中的自动装配有哪些限制&#xff1f; 4、 什么是可变参数&#xff1f; 5、 什么是领域模型(domain model)&#xff1f;贫血模型(anaemic domain model)和充血模…

Java基础习题库

Java基础习题库 目录 Java基础习题库 一、Java基础之概述 1.JDK,JRE,JVM三者之间的关系&#xff0c;以及JDK、JRE包含的主要结构有哪些 2.为什么要配置path环境变量&#xff1f;如何配置&#xff1f; 3.创建如下的类&#xff0c;使得运行的话可以输出&#xff1a; 4.编译…

Javase MINA框架

MINA是一个基于TCP/IP通信的JAVA框架&#xff0c;MINA可以帮助我们快速开发高性能、高扩展的网络通信应用&#xff0c;提供了事件驱动、异步操作的编程模型&#xff0c;默认使用NIO作为底层支持 客户端实现步骤&#xff1a;

基于Java后台(Springboot框架)+前端小程序(MINA框架)+Mysql数据库的疫苗预约小程序系统设计与实现

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序疫苗预约系统&#xff0c;前台用户使用小程序&#xff0c;后台管理使用基JAVAMySql技术&#xff1b;通过后台添加疫苗内容、价格、开放预约的日期和时间段&#xff0c;用户通过小程序登录&…

Spring Boot Starter之Mina框架封装

封装目的 目前是将Mina与Springboot的自动装配然后结合自身公司的业务对Mina进行统一的封装&#xff0c;目的是让代码可读性提高&#xff0c;也跟加便于使用&#xff0c;不用再写重复的代码 功能介绍 实现功能&#xff1a;可以通过注解的方式自动配置Mina服务端相关的代码 …

java mina 框架 获取字节_浅谈Java的Mina框架传递对象

接触java的Mina框架已经有很多时间了&#xff0c;在网上也读过了很多的相关文章&#xff0c;发现Mina框架的确是一个值得拿来好好研究的东西&#xff0c;前些日子写了一个山寨QQ项目&#xff0c;其中的通信部分用到了java中自带的InputStream&#xff0c;OutputStream&#xff…