为什么父进程的输出被子进程阻止?

时间:2015-11-24 15:17:11

标签: c++ fork

在下面的代码中,我将我的进程分为父进程和子进程。在子进程中,我将c字符串argv [1]发送到要打印的父进程。然后我让子进程在打印之前休眠4秒钟#34;这是子进程。闭\ n&#34 ;.

在父进程中,我希望子进程中的字符串在从子进程收到后立即打印到stdout。

问题出在这里。而不是在字符串&#34之前在父进程中立即打印argv [1];这是子进程。闭\ n"打印4秒后,会发生什么:

$ g ++ -std = c ++ 11 printchild.cpp -o printchild

$ ./printchild helloworld

1)通过4秒

2)"这是子进程。闭\ n"打印

3)" helloworld"打印

为什么父进程的输出被子进程阻止?

// printchild.cpp
#include <chrono>
#include <thread>
#include <cstdio>
#include <unistd.h>
#include <cstdlib>

int main(int argc, char * argv[]){
  int pipefd[2];
  pid_t cpid;
  if(argc != 2){
    fprintf(stderr, "Usage: %s <string>\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  if(pipe(pipefd) == -1){
    perror("fork");
    exit(EXIT_FAILURE);
  }
  cpid = fork();
  if(cpid == 0){
    close(pipefd[0]);
    FILE *fpc = fdopen(pipefd[1],"wb");
    fprintf(fpc,"%s",argv[1]);
    fflush(fpc);
    std::this_thread::sleep_for(std::chrono::seconds(4));
    fprintf(stdout,"This is the child process. Closing\n");
    return 0;
  }else if(cpid == -1){
    perror("Error in forking");
    exit(EXIT_FAILURE);
  }else{
    char str[80];
    close(pipefd[1]);
    FILE* fp = fdopen(pipefd[0], "rb");
    fgets(str,80,fp);
    fprintf(stdout,"%s\n",str);
    return 0;
  }
}

3 个答案:

答案 0 :(得分:2)

父进程正在通过500 Internal Server Error阅读孩子的邮件。它将继续阅读,直到发生以下三种情况之一:

  • 已经读取了足够的字节来填充缓冲区,少了一个字符串终结符
  • 读取换行符
  • 遇到文件结尾

子进程没有发送足够的字节来耗尽缓冲区,也没有发送换行符,因此父进程fgets()在子进程结束之前不会返回在退出时关闭。

您可以通过使用换行符终止消息或在写入后立即关闭流来解决此问题。

答案 1 :(得分:1)

如果您在刷新后立即关闭客户端中的文件,它将按预期工作:

fflush(fpc);
fclose(fpc);

输出:

[dbush] /tmp/x1 hello
hello
[dbush] This is the child process. Closing

答案 2 :(得分:1)

您的问题是fgets来电。 它试图完全满足您的要求,这是阻止的原因。

如果您正在对某些IPC进行原型设计,我建议您放弃stdio并转到原始IO系统调用。

如果你替换,例如:

char buf[100];
read(pipefd[0], buf, 100);
fprintf(stdout,"%s\n",buf);

对于fgets部分,您会立即收到您的消息,因为read会为您提供任何可用的内容并返回(如果有至少1个)在您发出read请求时,管道缓冲区中的字节,而fgets不会退回,直到它已读取所有请求的字节或直到它发现它可以&#39; t(EOF或IO错误)。

(为了分割头发,它不是fgets阻止(仅用户空间代码无法阻止) - 它是另一个暂时不可满足的{{1} } read已发出的系统调用。