[英]Why is output of parent process blocked by child process?
In my code below, I forked my process into a parent and child process. 在下面的代码中,我将进程分叉为父进程和子进程。 In the child process, I sent the c string argv[1] to the parent process to be printed.
在子进程中,我将c字符串argv [1]发送到父进程进行打印。 Then I made the child process sleep for 4 seconds before printing "This is the child process. Closing\\n".
然后,我让子进程休眠4秒钟,然后打印“这是子进程。正在关闭\\ n”。
In the parent process, I want the string from the child process to be printed to stdout as soon as I receive it from the child process. 在父进程中,我希望从子进程收到的字符串立即将其打印到stdout。
The problem arises here. 问题出现在这里。 Instead of immediately printing argv[1] in the parent process before the string "This is the child process. Closing\\n" is printed 4 seconds later, what happens is this:
而不是立即在字符串“ This is child process。Closing \\ n”显示在4秒后在父进程中立即打印argv [1]的情况是:
$ g++ -std=c++11 printchild.cpp -o printchild $ g ++ -std = c ++ 11 printchild.cpp -o printchild
$ ./printchild helloworld $ ./printchild helloworld
1) 4 seconds passes 1)4秒过去
2) "This is the child process. Closing\\n" is printed 2)打印“这是子进程。关闭\\ n”
3) "helloworld" is printed 3)打印“ helloworld”
Why is the output from the parent process blocked by the child process? 为什么父进程的输出被子进程阻止?
// 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;
}
}
The parent process is reading the child's message via fgets()
. 父进程正在通过
fgets()
阅读孩子的消息。 It will continue to read until one of three things happens: 它将继续读取,直到发生以下三种情况之一:
The child does not send enough bytes to exhaust the buffer, and it does not send a newline, so the parent's fgets()
does not return until the child's end of the pipe is closed upon its exit. 子级不会发送足够的字节来耗尽缓冲区,它也不会发送换行符,因此父级的
fgets()
不会返回,直到子级的管道末端在退出时关闭为止。
You can fix this in the child by having it either terminate the message with a newline or close the stream immediately after writing. 您可以通过让子进程以换行符终止消息或在写完后立即关闭流来解决此问题。
If you close the file in the client right after flushing, it will work as expected: 如果在刷新后立即在客户端中关闭文件,它将按预期工作:
fflush(fpc);
fclose(fpc);
Output: 输出:
[dbush] /tmp/x1 hello
hello
[dbush] This is the child process. Closing
Your problem is the fgets
call. 您的问题是
fgets
调用。 It tries to fulfill your request fully, and that's the cause of the blocking. 它会尝试完全满足您的要求,这就是阻塞的原因。
If you're prototyping some IPC, I recommend you ditch stdio
and go for the raw IO
syscalls. 如果您要制作一些IPC的原型,我建议您放弃
stdio
并进行原始的IO
系统调用。
If you substitute, eg: 如果替代,例如:
char buf[100];
read(pipefd[0], buf, 100);
fprintf(stdout,"%s\n",buf);
for the fgets
part, you'll get your message right away, because read
will give you whatever's available and return (if there's at least 1 byte in the pipe buffer at the time you make the read
request), whereas fgets
won't back off until it has read all the requested bytes or until it figures out it can't (EOF or an IO error). 对于
fgets
部分,您将立即收到消息,因为read
会为您提供可用的内容并返回(如果在发出read
请求时管道缓冲区中至少有1个字节),而fgets
不会返回直到读完所有请求的字节或发现无法读取为止(EOF或IO错误)。
(To split hairs, it's not fgets
that's blocking (userspace code alone can't block) -- it's another momentarily unsatisfiable read
syscall that fgets
has issued). (要乱发,不是
fgets
阻塞了(仅用户空间代码无法阻塞)-这是fgets
发出的另一个暂时无法满足的read
syscall)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.