【问题标题】:Piping the stdout of a command to the stdin of another other using shared file and dup2()使用共享文件和 dup2() 将命令的标准输出通过管道传输到另一个命令的标准输入
【发布时间】:2020-11-02 02:44:48
【问题描述】:

我正在编写一个带有两个参数的 porgram - 命令的名称。程序应该将第一个命令的输出重定向到文件“tmp”而不是执行它,而不是将第二个命令的标准输入重定向到“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);  
}

但是,当我像 ./main ls wc 这样运行程序时,而不是 5 5 50 我得到输出 0 0 0 这意味着 wc 命令从标准输入读取 0 个字节。 但是,如果我改为在同一个文件“tmp”上重新创建文件描述符,程序会给出正确的输出。如何解释这种行为?

【问题讨论】:

    标签: c unix posix file-descriptor dup


    【解决方案1】:

    这个问题基本上是Can anyone explain a simple description regarding 'file descriptor' after fork()? 的重复,但由于这有点微妙,我将解释这个具体案例。

    1. 进程打开一个文件。这将创建一个文件描述。文件描述是文件和文件描述符之间的中间概念。它们没有直接暴露在 Unix API 中,但除了它们指向的文件之外,它们还有一个重要的属性,我们稍后会看到。
    2. 孩子写到这个文件描述。家长等待。
    3. 父级从文件描述中读取。

    在第2步结束时,这个文件描述上的文件位置就是文件的结尾。所以在第 3 步,父级从文件末尾开始读取。

    如果在wait(NULL) 之后添加对rewind(fd) 的调用,子进程将从文件开头读取。

    如果您使用新的open 调用打开同一个文件,则会创建一个新的文件描述。 open 除非您设置附加模式,否则会将新文件描述的位置放在文件的开头。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 2015-06-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      相关资源
      最近更新 更多