dup2可以用newfd指定新描述符。若newfd已经打开,那么先将其关闭。若oldfd==newfd,那么返回newfd,不关闭它。 一个进程内dup和dup2函数执行以后内核的数据结构如上图所示。文件描述符指向的是同一个文件表。也拥有相同的文件偏移量。下面是一个简单的实例。
dup()函数和dup2()函数书上在文件操作那一章,已经讲过了,这周看重定向这块,发现它挺重要,就再看了回,记录下。 2、dup2函数 头文件及其定义: #include <unistd.h> int dup2(int oldfd, int newfd); dup2与dup区别是dup2可以用参数newfd dup2所复制的文件描述符与原来的文件描述符共享各种文件状态。共享所有的锁定,读写位置和各项权限或flags等. 返回值: 若dup2调用成功则返回新的文件描述符,出错则返回-1. ”>”)就是通过调用dup或dup2函数对标准输入和标准输出的操作来实现的。 printf("dup2的返回值:%d\n",fd); t=strlen(buf); if(write(fileno(stdout),buf,t)!
管道与重定向常常需要使用dup与dup2复制句柄,其中dup2又较为常用,但是使用dup2有几个小坑需要注意。 int dup2(int oldfd, int newfd); man手册页上是这样讲的,oldfd是想要复制的句柄,newfd是复制到的句柄号,如果newfd已经打开,dup2会先尝试关闭, 复制完成后 所以一般人可能会这样写代码: 1 if (dup2 (oldfd, newfd) ! = -1) 2 close (oldfd); 但是有个例外的情况,就是oldfd==newfd,照man手册页上讲,此时dup2将什么也不做,直接返回成功。 所以万无一失的dup2使用方法是这样: 1 if (oldfd != newfd) { 2 if (dup2 (oldfd, newfd) !
----今天接着昨天的话题讲,在昨天的文章里面,我们讲到了文件共享有三种实现方式,其中一种实现方式就是我们今天要讲的dup和dup2函数来实现了;那么咋们也就不废话 了,直接直奔主题吧。 (fd1,"ab",2); sleep(1); write(fd2,"cd",2); } close(fd1); return -1; } 二、dup2 函数解析: 1、相比于dup函数,dup2函数它的优势就是可以指定新的文件描述符的大小,用法比较灵活。 \n", fd1); fd2 = dup2(fd1, 16); printf("fd2 = %d. \n", fd2); close(fd1); return -1; } 2、dup2和dup函数一样对文件写操作都是接续写的,这里我就不做演示了,写法和dup函数一样。
3. dup()和dup2()函数 包含头文件 #include <unistd.h> 函数原型 int dup(int oldfd); int dup2(int oldfd, int newfd); 并且让这个文件描述符指向oldfd所指向的文件;dup() uses the lowest-numbered unused descriptor for the new descriptor. dup2 (oldfd, newfd):重定向,关闭newfd对应的文件使文件描述符newfd空闲,然后让newfd指向oldfd所指向的文件;dup2() makes newfd be the copy of If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing ); /*打开一个文件*/ int fd = open("hello.txt", O_WRONLY | O_CREAT, 0644); /*重定向标准输出1至文件*/ dup2
用指针的观点来深入理解dup和dup2的用法 作者:ejian 2007-09-17 网上有很多资料详细讲解了dup和dup2的用法,有讲得不错的,但总感觉理解起来还是有点困难,通过实践,我发现一种C程序更容易理解的讲解方法 -使用类比指针的方法来阐述dup和dup2的用法,可能更容易让人在非常短的时间内接受,下面的内容是我理解dup和dup2用法的总结,希望对dup和dup2存有疑惑的朋友所有帮助。 下面创建管道 int fd[2]; pipe(fd); // 下面这句相当于: // STDIN_FILENO = fd[0]; // 从这里可以看出STDIN_FILENO和stdinp指向了不同的位置 dup2 STDIN_FILENO可以替代fd[0]了,close(fd[0])相当于 // fd[0] = NULL; // 将fd[0]指向一个有效的安全值,关闭它 // 下面再说说如何恢复: // 只需要执行: dup2 不过,还有一点要请各位注意,dup和dup2的改变指向时会分配内存,所以在不使用时要记得打开,否则 你可能遇到“打开的文件过多”的错误,比如: int* stdinp =dup(STDIN_FILENO
1.文件描述符复制函数--dup/dup2/fcntl #include <unistd.h> int dup(int fd); /*复制一个现有文件的描述符*/ int dup2(int fd, int dup2()可以用fd2指定新描述符的值。如果fd2已经打开,则先将其关闭。若fd==fd2, 则dup2返回fd2,而不关闭它。 代码样例: Demo1: 重定向进程的stdin、stdout以及stderr到filename文件 int fd = open(filename, O_WRONLY, 0666); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); dup2(fd, STDERR_FILENO); Demo2: #include <stdio.h> #include fd_old = open("test.txt", O_RDWR | O_CREAT, 0666); int fd_new = dup(fd_old); int fd_new_2 = dup2
在 Arm 架构中,没有提供 Dup2 的方法,因此出现以上编译问题。 Dup3与Dup2参数略有差异,dup(int filedes)函数返回一个可用的与filedes共享文件表项的最小描述符。 而dup2(int filedes,int filedes2)是使用一个描述符filedes2去指向filedes2文件表项(也是共享),但是在调用dup2之前要确保filedes2为可用描述符。 在该问题中,我们查询在 Arm 架构的 linux 中实现了 Dup3 方法代替 Dup2,因此修改代码为 Dup3,即可解决该问题。
进程默认情况下会有3个缺省打开的文件描述符,分别是 stdin标准输入0, stdout标准输出1, stderro标准错误2. 0,1,2对应的 物理设备 一般是: 键盘,显示器,显示器 二.dup2 函数介绍 我们先了解这个dup2函数,功能是改变 底层fd的指向 #include <unistd.h> int dup2(int oldfd, int newfd); 参数: oldfd:这是你想要复制的文件描述符 底层访问文件的时候,找的还是fd:1, 但此时,fd:1下标所表示内容,已经变成了myfile的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写入,进而完成输出重定向 底层等效于dup2
nNullFile = open("/t.txt", O_CREAT | O_APPEND | O_WRONLY | O_TRUNC); assert(nNullFile>0); dup2 (nNullFile, STDIN_FILENO); dup2(nNullFile, STDOUT_FILENO); dup2(nNullFile, STDERR_FILENO
有的下面将介绍一下系统调用dup2() 1.4.3 dup2()系统调用 dup2 是 Unix/Linux 系统中的一个系统调用,用于复制一个文件描述符,并将其关联到另一个指定的文件描述符。 dup2原型: int dup2(int oldfd, int newfd); oldfd:原始的文件描述符,表示要复制的文件描述符。 可以使用 dup2 将标准输出(文件描述符 1)重定向到文件。 了解 dup2 的工作原理,可以让你在编写与文件操作相关的程序时,更加高效和灵活。 文章重点介绍了 文件重定向,尤其是如何通过 dup2() 系统调用实现标准输入输出的重定向,深入揭示了文件描述符在实际应用中的灵活性和重要性。
ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xE1 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xC6 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x10E JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1
read,但是pread又和这种顺序有重要区别: 一.调用pread时,无法中断其定位和读操作 二.不更新文件指针 调用pwrite相当于调用lseek和write 7 dup和dup2 函数(用来复制一个现存的文件描述符) #include <unistd.h> int dup(int filedes); int dup2(int filedes, int filedes2); Both return: new file descriptor if OK, -1 on error Dup()返回的新描述符一定是最小数值,而dup2()可以通过filedes2来指定新的描述符 复制一个描述符的另一种方法是fcntl函数 dup2(filedes, filedes2);等效于dup(filedes); fcntl(filedes, F_DUPFD, filedes2);等效于 dup2(filedes, filedes2); 当然了,dup2并不完全等同于close和fcntl.
open打开同一个文件,第二种是在不同进程中去分别使用open打开同一个文件(这时候因为两个fd在不同的进程中,所以两个fd的数字可以相同也可以不同),第三种情况是后面要学的,linux系统提供了dup和dup2 4、文件描述符的复制 使用dup和dup2进行文件描述符复制 int dup(int oldfd); int dup2(int oldfd, int newfd); dup系统调用对fd进行复制,会返回一个新的文件描述符 fcntl函数介绍 int fcntl(int fd, int cmd, ... /* arg */ ); fcntl的常用cmd F_DUPFD这个cmd的作用是复制文件描述符(作用类似于dup和dup2 ),这个命令的功能是从可用的fd数字列表中找一个比arg(用户指定的fd)大或者和arg一样大的数字作为oldfd的一个复制的fd,和dup2有点像但是不同。 dup2返回的就是我们指定的那个newfd否则就会出错,但是F_DUPFD命令返回的是>=arg的最小的那一个数字。 还有一些其他的cmd可以看手册,这里不多说了。
(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed" , log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } #if 0 if (dup2(fd, STDERR_FILENO ) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return (fd, STDIN_FILENO) == -1) { return -1; } if (dup2(fd, STDOUT_FILENO) == -1) { return -1; } #if 0 if (dup2(fd, STDERR_FILENO) == -1) { return -1; } #endif //
void drawpoly(int numpoints, int *polypoints);画多边形 int dup(int handle);复制文件描述符;若成功为新的文件描述,若出错为-1int dup2 6.3 运行结果7. dup27.1 函数说明函数声明函数功能 int dup2(int oldhandle, int newhandle);复制文件描述符;若成功为新的文件描述,若出错为-1。 dup2 可以用 newhandle 参数指定新的描述符数值。如果 newhandle 已经打开,则先关闭。 若 oldhandle = newhandle,则 dup2 返回 newhandle,而不关闭它。 (handle, STDOUT); close(handle); write(STDOUT, msg, strlen(msg)); dup2(oldstdout, STDOUT);
内建命令(cd、echo、export) 环境变量初始化(Initenv) 重定向解析(RedirCheck 与 TrimSpace) 外部命令执行(Excute:fork、dup2 子进程处理重定向: 输入重定向:open 目标文件(只读)→ dup2(fd,0) 把 stdin 重定向到该文件描述符 → close(fd)。 ., O_CREAT|O_WRONLY|O_TRUNC,0666) → dup2(fd,1) 把 stdout 指向文件。 追加:用 O_APPEND 打开并 dup2 到 1。 /myfile log1.txt (若 myfile 实现 open argv[1] 并 dup2(fd,0) 的那类) 行为: g_argv[0] = ". 重定向行为:重定向只在子进程中生效(通过 dup2),不会污染父进程的 stdin/stdout,这保证了 Shell 的持续可用性。
#include <unistd.h> //二者都是失败返回-1并设置errno int dup(int file_descriptor); //dup2可理解为后者重定向到前者 int dup2(int file_descriptor_one, int file_descriptor_two); 参数: dup和dup2的参数都是文件描述符,具体作用如下: dup函数创建一个新的文件描述符,该新的描述符和原有文件描述符 dup2函数与dup类似,不过它返回的是第一个不小于file_descriptor_tow的整数值 //例子。 close(STDOUT); dup(fd); printf("dup"); close(fd); } //使用dup2 void dup2_out(){ dup2(fd , STDOUT); printf("dup2"); close(fd); } 3. readv和writev readv函数将数据从文件描述符读到分散的内存块中,即分散读 writev
open("/dev/null", O_RDWR); // 打开空设备 if(fd == -1){ // 文件打开失败 写错误日志 return -1; } // 对于dup2 函数 如果第二个参数不是新的文件描述符 会先close第二个参数的文件描述符 然后再复制 if(dup2(fd, STDIN_FILENO) == -1){ // 重定向标准输入到空设备 // 写错误日志 return -1; } if(dup2(fd, STDOUT_FILENO) == -1){ // 重定向标准输出到空设备 // 写错误日志
可借助dup2让stdin复活: #include #include #include #include #include #include int main() { char buf[1024] = errno=%d: %m\n", n, errno); int fd = open("/tmp/abcde", O_RDONLY); printf("fd=%d\n", fd); if (-1 == dup2 (fd, 0)) printf("dup2 error: %m\n"); n = read(0, buf, sizeof(buf)-1); printf("n=%d, errno=%d: %m\n", include int main() { int n; char buf[1024]; // 重定向stdin到/dev/null int fd = open("/dev/null", O_RDWR, 0); dup2 fid = dup2(fildes, fildes2); // 重定向fildes2到fildes 等同于: close(fildes2); fid = fcntl(fildes, F_DUPFD