0

我正在编写一个将运行 Linux 命令的 C 程序,例如:

$ 猫 /etc/passwd | 切-f1 -d:| 种类

这个想法是使用 fork() 创建子进程以使用 execlp() 运行命令。我计划使用两个管道进行通信并使用 dup() 引导输入输出。

输出错误:

ls -l | wc -c on 命令返回 1746 程序返回 1761

代码(编辑以反映建议):

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

int main()
{
  int i,fd1[2],status,listpid[2];
  pid_t child;
  pipe(fd1);

  for(i=0; i< 2; i++)
  {
    printf("\ncreating child\n");
    if((child = fork()) == -1)
    {
      perror("fork");
      exit(EXIT_FAILURE);

    }
    else if(child == 0)
    {
      if(i == 0)
      {
    close(1); dup(fd1[1]);
    close(fd1[0]);
    close(fd1[1]);
    printf("\nrunning ls -l\n");
    fflush(stdout);
    execlp("ls","ls","-l", (char *)NULL);
    exit(EXIT_SUCCESS);

      }
      else if(i == 1)
      {
    close(0); dup(fd1[0]);
    close(fd1[1]);
    close(fd1[0]);
    printf("\nrunning wc -c\n");
    fflush(stdout);
    execlp("wc","wc","-c", (char *)NULL);
    exit(EXIT_SUCCESS);

      }

    }
    else
    {
      listpid[i]=child;
    }

  }

  close(fd1[0]);
  close(fd1[1]);

  for(i = 0; i < 2; i++) 
  {
    waitpid(listpid[i], &status, 0);

    if(WIFEXITED(status)) 
    {
      printf("\n[%d] TERMINATED (Status: %d)\n",listpid[i], WEXITSTATUS(status));

    }

  }
  exit(EXIT_SUCCESS);

}
4

2 回答 2

1

首先,您不能在循环中 waitpid ——如果 ls 的输出足够大,它将填满管道,因此在有人读取它之前它不会完成:您必须在 for 循环之后等待两个孩子。其次——只要管道的另一端打开,wc 就会继续运行,也就是说,您也必须关闭父管道中的管道。

于 2012-11-29T21:51:23.947 回答
0

更新后,两个子进程的行为正常。但是,您仍然需要添加:

close(fd1[0]);
close(fd1[1]);

for启动子项的for循环和收集退出状态的循环之间。

因为管道的写端仍然是打开的,wc没有收到EOF,所以它没有终止,所以你的进程无限期地等待。

于 2012-11-30T07:06:32.643 回答