管道问题:第一个孩子写了太多管道

时间:2016-11-14 11:04:43

标签: c linux fork system-calls execvp

我正在尝试在C中编写一个程序,该程序创建了2个子进程,每个进程都执行execvp

我的问题是,第一个孩子将太多输入写入另一个孩子读取的管道。

int main(int argc, char* argv[]){

//unnamed pipe
int pipeFd[2], statusFirst,statusSecond;
pid_t childPidOne,childPidTwo;

if(pipe(pipeFd) < 0){
    perror("Pipe error:\n");
    exit(EXIT_FAILURE);
}

switch(childPidOne = fork()){
    case -1:
        perror("First Fork error:\n");
        exit(EXIT_FAILURE);
    case 0:
        printf("First child\n");
        close(pipeFd[1]);
        if( (execvp(argv[1], &argv[1])) < 0){
            perror("First execvp error:\n");
        }
        printf("End First cild\n");
        exit(0);
    default:
        //Do nothing
        break;  
}

switch(childPidTwo = fork()){
    case -1:
        perror("Second Fork error:\n");
        exit(EXIT_FAILURE);
    case 0:
        printf("Second cild\n");
        close(pipeFd[0]);
        if( (execvp(argv[3], &argv[3])) < 0){
            perror("Second execvp error:\n");
        }
        printf("End Second cild\n");
        exit(0);
    default:
        //Do nothing
        break;  
}


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


if( (waitpid(childPidOne,&statusFirst,WUNTRACED | WCONTINUED)) < 0 ){
    perror("First waitpid error:\n");
}else{
    if (WIFEXITED(statusFirst)) {
       printf("First exited, status=%d\n", WEXITSTATUS(statusFirst));
    } else if (WIFSIGNALED(statusFirst)) {
       printf("First killed by signal %d\n", WTERMSIG(statusFirst));
    } else if (WIFSTOPPED(statusFirst)) {
       printf("First stopped by signal %d\n", WSTOPSIG(statusFirst));
    } else if (WIFCONTINUED(statusFirst)) {
       printf("First continued\n");
    }
}


if( (waitpid(childPidTwo,&statusSecond,WUNTRACED | WCONTINUED)) < 0 ){
    perror("Second waitpid error:\n");
}
if (WIFEXITED(statusSecond)) {
   printf("Second exited, status=%d\n", WEXITSTATUS(statusSecond));
  } else if (WIFSIGNALED(statusSecond)) {
   printf("Second killed by signal %d\n", WTERMSIG(statusSecond));
  } else if (WIFSTOPPED(statusSecond)) {
   printf("Second stopped by signal %d\n", WSTOPSIG(statusSecond));
  } else if (WIFCONTINUED(statusSecond)) {
      printf("Second continued\n");
      }

   exit(0);
return 0;
  }

也许我对pipe + fork + execvp的工作方式有错误的理解,所以让我告诉你我在代码中做了些什么:

  1. 我创建了一个未命名的管道 - 两个孩子都使用相同的管道
  2. 我将通过分叉创建两个孩子
  3. 因为我执行了这样的程序:./pipeline [FIRST SYSTEM CALL] | [SECOND SYSTEM CALL]或者只是举个例子:./pipeline echo Hello | wc -m我关闭了管道的阅读网站
  4. 然后致电execvp(argv[1], &argv[1])
  5. 这就是错误发生的地方(我猜): 我永远不会关闭写作方,直到第二个孩子这样做,因为如果成功,execvp将永远不会返回。

    我知道execvp不会关闭打开的文件描述符(可以使用What does the FD_CLOEXEC flag do?中提到的fcntl中的标记来关闭它。)

    实施例

    让我举个例子。

    echo Hello | wc -m
    

    输出结果

      

    6

    因为系统调用wc(字数统计)会计算给定-m

    中的字符(String

    这是正确的,因为hello = 5 + 1(我猜是\n\0),这就是6。

    现在,运行我的程序会得到结果

      

    56

    或获取更多信息

    echo hello | wc
    

    输出

      

    1(行)1(字)6(字符)

    ./pipeline echo hello | wc

    输出

      

    3(行)9(字)56(字符)

    我已经搜索了几天,但我无法弄明白。

    有什么想法吗?

    非常感谢!

1 个答案:

答案 0 :(得分:0)

自己解决了。

忘记使用dup2

只需在dup2命令后键入close命令,就可以了。