管道实现卡在dup2命令

时间:2016-02-23 17:54:16

标签: c shell pipe

我想要制作一个简单的外壳,但是我坚持实施管道。这是我的代码中与管道有关的部分。如果你认为它会有所帮助,我可以提出更多,但其余的工作完全符合预期。

    args[i] = NULL;
    p_flag = 1;
    int stop = i;
    // we have to fork again so we can write to a buffer file.
    // First we creat the pipe.
    if (pipe(p_file) == -1) {
      //check if the pipe failed
      fprintf(stderr, "There was an error creating the pipe\n");
    }
    switch (pid = fork()) {
    case 0:
      //Open up the input end of the pipe for writing.
      printf("test1\n");
      close(p_file[0]);
      printf("test2\n");
      dup2(p_file[1], 1);
      printf("test3\n");
      execvp(args[0], args);
      fprintf(stderr, "ERROR %s no such program.\n", line);
      exit(1);
      break;
    case -1:
      fprintf(stderr, "ERROR can't create child process!\n");
      break;
    default:
      wait();
      break;
    }
    /*
      at this point only the first child should still be running
      and since we waited we know that the buffer file has our input.
      Now we have to redirect our input to read from the buffer and
      run the rest of the commands normally. first the args array has
      to be cleaned up we want the commands past the pipe symbol to be
      in front.
    */
    int j = 0;
    stop++;
    while (args[stop] != NULL) {
      args[j] = args[stop];
      j++;
      stop++;
    }
    args[j] = NULL;
    close(p_file[1]);
    dup2(p_file[0], 0);

正如你所看到的,我已经添加了一些打印语句来试图弄清楚它到底卡在哪里,并且在程序处理永久旋转之前我得到test1test2输出它的轮子。我必须按ctrl + c才能得到提示。我不知道为什么它会卡在dup2命令中。这个代码段中唯一遗漏的是p_file的初始化,它是一个大小为2的数组(即int p_file[2];)。

1 个答案:

答案 0 :(得分:2)

你有一个严重的误解。管道是一种进程间通信机制。通过管道进行通信的进程通常同时运行,而不是顺序运行。它们必须在通用实现中并发运行,例如shell提供的实现,因为每个管道只有一个有限的缓冲区,并且当缓冲区填充时,写入它将阻塞或失败。除非您可以确定写入程序在退出之前不会填充管道的缓冲区,否则读者必须准备好并等待从管道的读取端使用数据,然后您才能期望写入程序完成。

因为第一个进程在开始第二个进程之前wait()是错误的,这可能就是你的程序挂起的原因。相反,shell必须为管道的每一端启动子进程,然后等待两者。

此外,正如我在评论中所写,你没有正确的参数就调用wait()。这会产生未定义的行为,这本身可能是无限期的等待,但也可能是其他任何行为。

至于你的调试输出,@ Ctx在他自己的评论中解释了为什么你没有看到你期望的一切。但是,我不认为有任何理由怀疑你声称该程序在你打断它之前就会挂起。