dup和dup2函数

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);

作用:dup函数实现对一个文件的文件描述符进行复制,复制之后该进程就会新增加一一个文件描述符指向该文件(即实现同一个文件对应多个文件描述符)。dup2函数:如果new是一个被打开的文件描述符(与old不是同一个文件),则在拷贝前先关闭new(new就不需要占据那个文件描述符了),即使new文件的文件描述符重新指向old文件;如果两个文件描述符对应的是同一个文件,则直接返回文件描述符。  文件描述符的复制又称为文件描述符的重定向。

dup返回值:返回新的文件描述符(文件描述符表中最小的未被占用的文件描述符)。 出错,返回-1。

dup2返回值:如果两个文件描述符对应的是同一个文件,则直接返回文件描述符。(不拷贝)。如果不是同一个文件,则返回new的那个文件描述符。出错 返回-1。

//dup函数代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{int fd = open("a.txt", O_RDWR); //文件第一次被打开时,其文件指针置于文件首部if(fd == -1){perror("open");exit(1);}printf("file open fd = %d\n", fd);int ret = dup(fd);  //文件描述符的复制(重定向)if(ret == -1){perror("dup");exit(1);}printf("dup fd = %d\n", ret);char* buf = "你是猴子派来的救兵吗????\n";char* buf1 = "你大爷的,我是程序猿!!!\n";write(fd, buf, strlen(buf));  //通过fd来向文件写入数据write(ret, buf1, strlen(buf1));  //通过ret来向同一文件继续写入数据,注意是追加写入,因为一个文件的文件读写指针只有一个,因此第一个文件操作后,第二个接着第一个的位置继续进行。close(fd);  //此时只是释放了fd,但还是可以通过ret来使用该文件。close(ret);  //释放retreturn 0;
}//dup2函数代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main( )
{int fd = open("english.txt", O_RDWR);if(fd == -1){perror("open");exit(1);}int fd1 = open("a.txt", O_RDWR);if(fd1 == -1){perror("open");exit(1);}printf("fd = %d\n", fd);printf("fd1 = %d\n", fd1);int ret = dup2(fd1, fd);  //此时先关闭fd,然后再将fd分配给a.txtif(ret == -1){perror("dup2");exit(1);}printf("current fd = %d\n", ret);char* buf = "主要看气质 ^_^!!!!!!!!!!\n";write(fd, buf, strlen(buf));write(fd1, "hello, world!", 13);close(fd);close(fd1);return 0;
}

[root@localhost dup]# ./dup2

fd = 3

fd1 = 4

current fd = 3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fcntl函数(网络编程会用)

#include <unistd.h> #include <fcntl.h> int fcntl&#xff08;int fd, int cmd&#xff09;&#xff1b; int fcntl&#xff08;int fd, int cmd, long arg&#xff09;&#xff1b;//long 长整型 int fcntl&#xff08;int fd, int cmd, struct flock *lock…

189. 旋转数组

给定一个数组&#xff0c;将数组中的元素向右移动 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: [1,2,3,4,5,6,7] 和 k 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,5] 向右旋转 3 步: [5,6,7,1,2,3,4]示例 2: 输…

58. 最后一个单词的长度

给定一个仅包含大小写字母和空格 的字符串&#xff0c;返回其最后一个单词的长度。 如果不存在最后一个单词&#xff0c;请返回 0 。 说明&#xff1a;一个单词是指由字母组成&#xff0c;但不包含任何空格的字符串。 示例: 输入: "Hello World" 输出: 5 clas…

CPU和MMU(内存管理单元)

CPU的架构&#xff1a;要求能够理解从源程序到微指令的整个经历过程&#xff1a;存储器的层次结构&#xff08;网络资源下载到硬盘、磁盘缓存、内存、Cache、寄存器&#xff09;&#xff1b;CPU的四大部分&#xff1a;ALU、CU、中断系统和寄存器&#xff1b;程序执行的整个过程…

【C++ Primer | 09】容器适配器

一、stack s.push(): 向栈内压入一个成员&#xff1b; s.pop(): 从栈顶弹出一个成员&#xff1b; s.empty(): 如果栈为空返回true&#xff0c;否则返回false&#xff1b; s.top(): 返回栈顶&#xff0c;但不删除成员&#xff1b; s.size(): 返回栈内元素…

进程控制块PCB(进程描述符)

&#xff08;1&#xff09;PCB 每个进程在内核中都有一个进程控制块&#xff08;PCB&#xff09;来维护进程相关的信息&#xff0c;Linux内核的进程控制块是task_struct结构体。grep -r “task_struct” / 可以查找根目录下&#xff0c;包含task_struct的文件文件。或者 find…

103. 二叉树的锯齿形层次遍历

给定一个二叉树&#xff0c;返回其节点值的锯齿形层次遍历。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。 例如&#xff1a; 给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 /…

fork、getpid、getppid函数

#include <unistd.h> pid_t fork(void); 作用&#xff1a;创建一个子进程。 到目前为止&#xff0c;我们可以直到两种创建进程的方法&#xff1a;1. 通过执行二进制文件来创建一个进程&#xff0c;如&#xff1a;./a.out /bin/ls&#xff1b;2.通过fork函数来创建一个…

107. 二叉树的层次遍历 II

给定一个二叉树&#xff0c;返回其节点值自底向上的层次遍历。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 例如&#xff1a; 给定二叉树 [3,9,20,null,null,15,7], 3/ \9 20/ \15 7返回其自底向上的层次遍历为&#xff…

循环创建N个子进程

以循环创建5个进程为例&#xff0c;给出如下代码&#xff0c;分析其错误&#xff1a; #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(void) {int i;pid_t pid;printf("xxxxxxxxxxx\n");for (i 0; i < 5; i){pid fork…

【C++ Primer | 19】控制内存分配

1. 测试代码&#xff1a; #include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;if (void* p…

getuid、geteuid、getgid和getegid函数

#include <unistd.h> #include <sys/types.h> uid_t getuid(void); uid_t geteuid(void); 作用&#xff1a;getuid返回当前进程的实际用户ID&#xff1b;geteuid返回当前用户的有效用户ID。这两个总是成功&#xff0c;不会失败。 #include <unistd.h> #…

【第15章】虚函数

一、为什么基类中的析构函数要声明为虚析构函数&#xff1f; 直接的讲&#xff0c;C中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说&#xff0c;如果派生类中申请了内存空间&#xff0c;并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数&am…

进程共享(读时共享写时复制)

父子进程之间在刚fork后。父子相同处: 全局变量、.data、.bbs、.text、栈、堆、环境变量、用户ID、宿主目录&#xff08;进程用户家目录&#xff09;、进程工作目录、信号处理方式等等&#xff0c;即0~3G的用户空间是完全一样的。父子不同处: 1.进程ID 2.fork返回值 3.父进…

【C++ Primer | 08】IO库

一、istringstream类 描述&#xff1a;从流中提取数据&#xff0c;支持 >> 操作 这里字符串可以包括多个单词&#xff0c;单词之间使用空格分开 #include <iostream> #include <sstream> using namespace std; int main() {istringstream istr(&quo…

gdb调试(如何跟踪指定进程)

使用gdb调试的时候&#xff0c;gdb只能跟踪一个进程。可以在fork函数调用之前&#xff0c;通过指令设置gdb调试工具跟踪父进程或者是跟踪子进程。默认跟踪父进程。 set follow-fork-mode child 命令设置gdb在fork之后跟踪子进程。 set follow-fork-mode parent 设置跟踪父进程…

【Leetcode | 01】Backtracking

回溯算法序号题号117. 电话号码的字母组合222. 括号生成 39. 组合总和 40. 组合总和 II 46. 全排列 47. 全排列 II 60. 第k个排列 77. 组合 78. 子集 90. 子集 II 93. 复原IP地址 131. 分割回文串 216. 组合总和 III 306. 累加数 357. 计算各个位数不同的数字个数 401. 二进…

1033. 旧键盘打字(20)

旧键盘上坏了几个键&#xff0c;于是在敲一段文字的时候&#xff0c;对应的字符就不会出现。现在给出应该输入的一段文字、以及坏掉的那些键&#xff0c;打出的结果文字会是怎样&#xff1f; 输入格式&#xff1a; 输入在2行中分别给出坏掉的那些键、以及应该输入的文字。其中对…

1038. 统计同成绩学生(20)

本题要求读入N名学生的成绩&#xff0c;将获得某一给定分数的学生人数输出。 输入格式&#xff1a; 输入在第1行给出不超过105的正整数N&#xff0c;即学生总人数。随后1行给出N名学生的百分制整数成绩&#xff0c;中间以空格分隔。最后1行给出要查询的分数个数K&#xff08;不…

EXEC函数族的一般规律

事实上&#xff0c;只有execve是真正的系统调用&#xff0c;其它五个函数最终都调用execve&#xff0c;所以execve在man手册第2节&#xff0c;其它函数在man手册第3节。这些函数之间的关系如下图所示。