如何循环stdin&管道输出到C中的子execl命令?

时间:2013-05-11 22:20:37

标签: c unix fork pipe stdin

我一直试图找出如何从文件中循环stdin,然后将其发送到使用execl()对int进行排序的子进程。下面的代码的工作原理是它需要文件&排序,但我没有看到我添加的“句末”调试字符串。不知何故,这部分代码被绕过了。我可以使用一些帮助来理解文件中的数据流,然后将其打印到屏幕上。

int main(int argc, char *argv[])
{
  pid_t p;
  int status;
  int fds[2];
  FILE *writeToChild;
  char word[50];

  if(pipe(fds) == -1) {
    perror("Error creating pipes");
    exit(EXIT_FAILURE);
  }

  switch(p = fork()) {
  case 0: //this is the child process
    close(fds[1]); //close the write end of the pipe
    execl("/usr/bin/sort", "sort", (char *) 0);
    break;
  case -1: //failure to fork case
    perror("Could not create child");
    exit(EXIT_FAILURE);
  default: //this is the parent process
    close(fds[0]); //close the read end of the pipe
    writeToChild = fdopen(fds[1], "w");
    wait(&status);
    break;
  }

  while (fscanf(stdin, "%s", word) != EOF) {
    //the below isn't being printed.  Why?
    fprintf(writeToChild, "%s end of sentence\n", word); 
  }

  return 0;
}

1 个答案:

答案 0 :(得分:2)

您的主要问题是您将wait()放在错误的位置。在你写完任何东西之前,你等待孩子死亡。您还有一个次要问题,即不会将管道的读取端重定向到sort进程的标准输入。

你没有关闭孩子的fds[0];清洁度表明你应该。在等待之前你需要fclose(writeToChild);在父管关闭管道之前,排序不会停止。

这些变化(以及其他一些变化)导致:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    pid_t p;
    int status;
    int fds[2];
    FILE *writeToChild;
    char word[50];

    if (pipe(fds) == -1)
    {
        perror("Error creating pipes");
        exit(EXIT_FAILURE);
    }

    switch (p = fork())
    {
        case 0: //this is the child process
            close(fds[1]); //close the write end of the pipe
            dup2(fds[0], 0);
            close(fds[0]);
            execl("/usr/bin/sort", "sort", (char *) 0);
            fprintf(stderr, "Failed to exec sort\n");
            exit(EXIT_FAILURE);

        case -1: //failure to fork case
            perror("Could not create child");
            exit(EXIT_FAILURE);

        default: //this is the parent process
            close(fds[0]); //close the read end of the pipe
            writeToChild = fdopen(fds[1], "w");
            break;
    }

    if (writeToChild != 0)
    {
        while (fscanf(stdin, "%49s", word) != EOF)
        {
            //the below isn't being printed.  Why?
            fprintf(writeToChild, "%s end of sentence\n", word); 
        }
        fclose(writeToChild);
    }

    wait(&status);

    return 0;
}