C 使用共享文件和dup2()将命令的stdout管道化到另一个命令的stdin

C 使用共享文件和dup2()将命令的stdout管道化到另一个命令的stdin,c,unix,posix,file-descriptor,dup,C,Unix,Posix,File Descriptor,Dup,我正在写一个带有两个参数的程序包——命令名。程序应该将第一个命令的输出重定向到一个文件“tmp”,然后执行它,然后将第二个命令的stdin重定向到“tmp”,然后执行第二个命令 #include<unistd.h> #include<fcntl.h> #include<wait.h> #include<stdio.h> int main(int argc, char** argv){ int fd = open("tmp&qu

我正在写一个带有两个参数的程序包——命令名。程序应该将第一个命令的输出重定向到一个文件“tmp”,然后执行它,然后将第二个命令的stdin重定向到“tmp”,然后执行第二个命令


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

int main(int argc, char** argv){
    int fd = open("tmp", O_RDWR |O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
    int cpid = fork();
    
    if(cpid == 0){  
        dup2(fd, 1);
        execlp(argv[1], "", NULL);          
    }
    
    wait(NULL); 
    //If we uncoment this line the program gives correct output
    //fd = open("tmp", O_RDWR, S_IRUSR | S_IWUSR);
 
    dup2(fd, 0);
    
    execlp(argv[2], "", NULL);  
}

#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
int fd=开放(“tmp”,O|RDWR | O|TRUNC | O|CREAT,S|IRUSR | S|IWUSR);
int cpid=fork();
如果(cpid==0){
dup2(fd,1);
execlp(argv[1],“”,NULL);
}
等待(空);
//如果我们取消注释这一行,程序将给出正确的输出
//fd=开放(“tmp”,O_RDWR,S_IRUSR | S_IWUSR);
dup2(fd,0);
execlp(argv[2],“”,NULL);
}
但是,当我运行像
/main ls wc
这样的程序而不是
5550
我得到输出
0
,这意味着
wc
命令从stdin读取0字节。
但是,如果我在同一个文件“tmp”上重新创建文件描述符,程序将给出正确的输出。如何解释这种行为?

这个问题基本上是重复的,但由于这有点微妙,我将解释这个具体案例

  • 该过程将打开一个文件。这将创建一个文件描述。文件描述是文件和文件描述符之间的中间概念。它们不是直接在unixapi中公开的,但是除了它们指向的文件之外,它们还有一个重要的属性,稍后我们将看到
  • 子项写入此文件描述。家长等待
  • 父级从文件描述中读取
  • 在步骤2的末尾,此文件描述上的文件位置是文件的结尾。因此,在步骤3,父级开始读取文件的末尾

    如果在
    wait(NULL)
    之后添加对
    revind(fd)
    的调用,则子级将从文件开头读取

    如果使用新的
    open
    调用打开同一文件,将创建新的文件描述<代码>打开将新文件描述的位置放在文件开头,除非您设置了附加模式

    可以通过任意数量的文件描述符访问相同的文件描述,可能是在不同的进程中。文件位置是文件描述的一个属性,因此任何通过一个文件描述符移动它(读取、写入、查找)的操作都会将它移动到其他文件描述符,即使在不同的过程中也是如此