C++ 为什么父进程的输出被子进程阻止?
在下面的代码中,我将进程分为父进程和子进程。在子进程中,我将c字符串argv[1]发送到要打印的父进程。然后我让子进程休眠4秒钟,然后打印“这是子进程。正在关闭\n” 在父进程中,我希望从子进程接收到字符串后,立即将其打印到标准输出 问题就出现在这里。在4秒后打印字符串“This is the child process.Closing\n”之前,不是立即在父进程中打印argv[1],而是发生以下情况: $g++-std=c++11 printchild.cpp-o printchild $。/printchild helloworld 1) 4秒过去了 2) 打印“这是子进程。正在关闭\n” 3) “helloworld”是印刷品 为什么父进程的输出被子进程阻止C++ 为什么父进程的输出被子进程阻止?,c++,fork,C++,Fork,在下面的代码中,我将进程分为父进程和子进程。在子进程中,我将c字符串argv[1]发送到要打印的父进程。然后我让子进程休眠4秒钟,然后打印“这是子进程。正在关闭\n” 在父进程中,我希望从子进程接收到字符串后,立即将其打印到标准输出 问题就出现在这里。在4秒后打印字符串“This is the child process.Closing\n”之前,不是立即在父进程中打印argv[1],而是发生以下情况: $g++-std=c++11 printchild.cpp-o printchild $。/
// 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;
}
}
//printchild.cpp
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
int-pipefd[2];
pid_t cpid;
如果(argc!=2){
fprintf(stderr,“用法:%s\n”,argv[0]);
退出(退出失败);
}
如果(管道(管道FD)=-1){
佩罗尔(“福克”);
退出(退出失败);
}
cpid=fork();
如果(cpid==0){
关闭(pipefd[0]);
文件*fpc=fdopen(pipefd[1],“wb”);
fprintf(fpc,“%s”,argv[1]);
fflush(fpc);
std::this_thread::sleep_for(std::chrono::seconds(4));
fprintf(stdout,“这是子进程。正在关闭\n”);
返回0;
}否则如果(cpid==-1){
perror(“分叉错误”);
退出(退出失败);
}否则{
char-str[80];
关闭(pipefd[1]);
文件*fp=fdopen(pipefd[0],“rb”);
fgets(str,80,fp);
fprintf(stdout,“%s\n”,str);
返回0;
}
}
如果在刷新后立即关闭客户端中的文件,它将按预期工作:
fflush(fpc);
fclose(fpc);
输出:
[dbush] /tmp/x1 hello
hello
[dbush] This is the child process. Closing
父进程正在通过
fgets()
读取子进程的消息。它将继续阅读,直到发生以下三种情况之一:
- 已读取足够的字节以填充缓冲区,少于一个用于字符串终止符的字节
- 读一行新行
- 遇到文件结尾
fgets()
不会返回,直到子级的管道末端在退出时关闭
您可以在子级中修复此问题,方法是让它在写入消息后立即用换行符终止消息或关闭流。您的问题是
fgets
调用。
它试图完全满足您的请求,这就是阻塞的原因
如果您正在原型化一些IPC,我建议您放弃stdio
,转而使用原始IO
syscalls
如果替换,例如:
char buf[100];
read(pipefd[0], buf, 100);
fprintf(stdout,"%s\n",buf);
对于fgets
部分,您将立即收到消息,因为read
将提供所有可用信息并返回(如果在发出read
请求时管道缓冲区中至少有1个字节),然而,fgets
在读取所有请求的字节之前,或者在发现无法返回之前,不会后退(EOF或IO错误)
(说白了,阻塞的不是fgets
(用户空间代码本身无法阻止)--而是fgets
发出的另一个暂时不可满足的read
syscall)