通过管道使用进程来执行 运行 命令

Using processes to run commands with pipes

我对进程、管道和 dup2 还是个新手,因此我希望有人能帮我弄清楚我创建的程序有什么问题。这个程序应该运行 ls | wc。到目前为止,我得到的输出是:

wc : standard input : Bad file descriptor
        0         0         0
ls : write error : Bad file descriptor

在我得到这个输出后,终端仍然接受输入。就像 wc 仍然是 运行ning,虽然如果我先输入像 ls 这样的命令(之前没有任何其他输入)它 运行s 它们并关闭。我尝试了 运行ning ps before/after 并且程序仍在 运行ning 并且它没有显示任何进程正在打开,除了 bash 和 ps。 (我正在 运行 在 Linux 终端中安装这个程序)

这是我的代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<errno.h>

int main(int argc, char* argv[]){
      pid_t pid;
      int fd[2];
      char com1[1024] = ("ls");
      char com2[1024] = ("wc");
      pipe(fd);
      pid = fork();
      if(pid == 0){
           open(fd[1]);
           dup2(fd[0],STDOUT_FILENO);
           close(fd[0]);
           execlp(com1, com1, NULL);
                  }
      else {
           pid = fork();
           if (pid == 0){
                   open(fd[0]);
                   dup2(fd[1],STDIN_FILENO);
                   close(fd[1]);
                   execlp(com2, com2, NULL);
                         }
           }
return 0;
}

请记住,我知道一些 if 命令需要检查(如 if(pid<0)exit(0);),但我尽量简化我的代码,以查看是否由于粗心而导致错误。 提前致谢!

根据the pipe manual page

pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe.

现在从第一个子进程(调用 ls 命令的进程)中获取这一行:

dup2(fd[0],STDOUT_FILENO);

在这里,您将管道的 read 端复制到 STDOUT_FILENO,即写入输出的位置。如果您停下来想一想,您将如何写入像 fd[0] 这样的只读文件描述符?

与其他子进程相同,您将管道标准输入的 write 结束。

解决方法很简单:交换您复制的描述符的位置。第一个子进程使用 fd[1],第二个子进程使用 fd[0]

在您调用 ls 命令的第一个进程中:

dup2(fd[1],STDOUT_FILENO);
close(fd[1]);
execlp(com1, com1, NULL);

并且在您调用 wc 命令的第二个子进程中:

dup2(fd[0],STDIN_FILENO);
close(fd[0]);
execlp(com2, com2, NULL);