我知道dup、dup2、dup3会“创建文件描述符oldfd的副本”(摘自man页面)。但是我无法理解。
据我所知,文件描述符只是用于跟踪文件位置和方向(输入/输出)的数字。直接复制它们不是更容易吗?
fd=fd2;
每当我们想要复制文件描述符时?
还有一些其他的事情...
dup()使用未使用的最低编号描述符作为新描述符。
这是否意味着它也可以将stdin,stdout或stderr作为值,如果我们假设关闭了其中一个?
在做了一些实验后,我想回答一下我的第二个问题。
答案是是。如果stdin、stdout或stderr被关闭,你创建的文件描述符可以取值0、1或2。
例如:
close(1); //closing stdout
newfd=dup(1); //newfd takes value of least available fd number
当这种情况发生在文件描述符上时:
0 stdin .--------------. 0 stdin .--------------. 0 stdin
1 stdout =| close(1) :=> 2 stderr =| newfd=dup(1) :=> 1 newfd
2 stderr '--------------' '--------------' 2 stderr
dup()
操作? - Pithikos文件描述符不仅仅是一个数字,它还携带各种半隐藏的状态(比如它是否打开,它指向哪个文件描述符,以及一些标志位)。dup
会复制这些信息,这样你就可以独立关闭两个描述符。但是fd=fd2
则不行。
dup
函数族克隆该数据结构中节点的状态,并将新节点的索引交给您。 - dmckee --- ex-moderator kittendup()
复制。这就是程序员需要知道的全部内容。顺便说一下,这不是非常有趣的数据,它只是几个标志和对真正有趣的数据(打开文件描述符)的索引,这个数据不会被dup()
复制。 - n. m.fdin = open(infile, O_RDONLY);
fdout = open(outfile, O_WRONLY);
// Check for errors, send messages to stdout.
...
int pid = fork(0);
if(pid == 0) {
close(0);
dup(fdin);
close(fdin);
close(1);
dup(fdout);
close(fdout);
execvp(program, argv);
}
// Parent process cleans up, maybe waits for child.
...
dup2()是一种更方便的方法,用于替换close() dup()的操作:
dup2(fdin, 0);
dup2(fdout, 1);
你想这样做的原因是要将错误报告到stdout(或stderr),所以不能关闭它们并在子进程中打开新文件。其次,如果任一open()调用返回错误,则进行fork将是浪费。
dup()最重要的一点是它返回一个可用于新文件描述符的最小整数。这是重定向的基础:
int fd_redirect_to = open("file", O_CREAT);
close(1); /* stdout */
int fd_to_redirect = dup(fd_redirect_to); /* magically returns 1: stdout */
close(fd_redirect_to); /* we don't need this */
在此之后,任何写入文件描述符1(标准输出)的内容都会神奇地进入“文件”中。
我怀疑你使用展示的结果进行以上实验,因为那不符合标准 - 参见dup:Example:
close(1); //closing stdout newfd=dup(1); //newfd takes value of least available fd number
Where this happens to file descriptors:
0 stdin .--------------. 0 stdin .--------------. 0 stdin 1 stdout =| close(1) :=> 2 stderr =| newfd=dup(1) :=> 1 newfd 2 stderr '--------------' '--------------' 2 stderr
A question arose again: How can I
dup()
a file descriptor that I already closed?
所以,在展示代码序列之后,dup()函数会失败,如果:
[EBADF] fildes参数不是有效的打开文件描述符。
newfd
必须不是1
,而是-1
,并且errno
是EBADF
。我有一个关于“复制标准输出”的提示。
在一些Unix系统上(但不包括GNU / Linux)
fd = open("/dev/fd/1", O_WRONLY);
it is equivalent to:
fd = dup(1);
dup()和dup2()系统调用
• dup()系统调用复制一个打开的文件描述符并返回新的文件描述符。
• 新的文件描述符与原始文件描述符具有以下共同属性: 1. 指向相同的打开文件或管道。 2. 具有相同的文件指针--也就是说,两个文件描述符共享一个文件指针。 3. 具有相同的访问模式,无论是读、写还是读写。
• dup()保证返回具有最低整数值的文件描述符。正是由于这个特性返回了最低未使用的文件描述符,使得进程可以完成I/O重定向。
int dup(file_descriptor)
int dup2(file_descriptor1, file_descriptor2)
dup
是告诉内核你希望它继续跟踪其中另一个文件句柄(指向同一文件),直到你使用close
关闭它。 - user786653