C语言 如何等到数据写入管道的另一端
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15196784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wait till data is written on the other end of pipe
提问by User007
I am developing an application in C. Parent and child process communicate through pipe. Before writing to pipe, parent process execute another statements. In sample code, i have used sleep(10) to make delay. In the child process, it should read the data from the pipe. But data is not read on the read end of pipe in child process.
我正在用 C 开发一个应用程序。父子进程通过管道进行通信。在写入管道之前,父进程执行另一条语句。在示例代码中,我使用 sleep(10) 进行延迟。在子进程中,它应该从管道中读取数据。但是在子进程的管道读取端没有读取数据。
int main()
{
int pid;
FILE *fp;
fp = fopen("test.txt","w");
char *buff;
int fd[2];
int count = 0 ;
pipe(fd);
pid = fork();
if(pid == 0)
{
close(fd[1]);
ioctl(fd[0], FIONREAD, &count);
fprintf(fp,"Value of count: %d ",count);
buff = malloc(count);
fprintf(fp,"\n TIME before read: %s",__TIME__);
read(fd[0], buff, count);
fprintf(fp,"\nbuffer: %s\n TIME after read %s", buff, __TIME__);
}
else{
close(fd[0]);
sleep(10); //delay caused by application specific code replaced with sleep
write(fd[1],"THIS is it",10);
}
fclose(fp);
return 0;
}
How to make child process wait till data is written on the other end?
如何让子进程等待数据写入另一端?
采纳答案by WhozCraig
Your pipe is opened in blocking mode, and you do nothing to change that, which is likely what you intended.
您的管道以阻塞模式打开,您没有做任何更改,这可能是您的意图。
However, since the first thing you do is request the size of data waiting on the pipe, then blindly jump into reading that many bytes (which in all likelihood will be zero at the time that code executes since the parent hasn't written anything yet) you don't block, and instead just leave because you requested nothing.
但是,由于您做的第一件事是请求在管道上等待的数据的大小,然后盲目跳入读取那么多字节(在代码执行时很可能为零,因为父级尚未写入任何内容) ) 你没有阻止,而是离开,因为你什么也没要求。
There are a number of ways to do this, including a select-loop. If you would rather blockon a read until data is available, then do so on a single byte and fill in the remaining data afterward.
有多种方法可以做到这一点,包括选择循环。如果您更愿意在数据可用之前阻塞读取,则在单个字节上执行此操作,然后填充剩余的数据。
This is by no means an example of how to do this right, but it is a short sample of how you can wait on a single byte, request the read-size of the pipe to get the rest of the data, read it, and continue this until the pipe has no data left and the parent shuts down their end:
这绝不是如何正确执行此操作的示例,但它是如何等待单个字节、请求管道的读取大小以获取其余数据、读取它以及继续这样做,直到管道没有剩余数据并且父级关闭它们的末端:
I hope you find it helpful.
我希望你觉得这对你有帮助。
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main()
{
int pid = 0;
// create pipe pair
int fd[2];
pipe(fd);
pid = fork();
if (pid == 0)
{
// child side
char *buff = NULL;
char byte = 0;
int count = 0;
// close write side. don't need it.
close(fd[1]);
// read at least one byte from the pipe.
while (read(fd[0], &byte, 1) == 1)
{
if (ioctl(fd[0], FIONREAD, &count) != -1)
{
fprintf(stdout,"Child: count = %d\n",count);
// allocate space for the byte we just read + the rest
// of whatever is on the pipe.
buff = malloc(count+1);
buff[0] = byte;
if (read(fd[0], buff+1, count) == count)
fprintf(stdout,"Child: received \"%s\"\n", buff);
free(buff);
}
else
{ // could not read in-size
perror("Failed to read input size.");
}
}
// close our side
close(fd[0]);
fprintf(stdout,"Child: Shutting down.\n");
}
else
{ // close read size. don't need it.
const char msg1[] = "Message From Parent";
const char msg2[] = "Another Message From Parent";
close(fd[0]);
sleep(5); // simulate process wait
fprintf(stdout, "Parent: sending \"%s\"\n", msg1);
write(fd[1], msg1, sizeof(msg1));
sleep(5); // simulate process wait
fprintf(stdout, "Parent: sending \"%s\"\n", msg2);
write(fd[1], msg2, sizeof(msg2));
close(fd[1]);
fprintf(stdout,"Parent: Shutting down.\n");
}
return 0;
}
Output
输出
Parent: sending "Message From Parent"
Child: count = 19
Child: received "Message From Parent"
Parent: sending "Another Message From Parent"
Parent: Shutting down.
Child: count = 27
Child: received "Another Message From Parent"
Child: Shutting down.
回答by B?ови?
The problem is with getting number of bytes written to the pipe. You are getting it right after the fork(). If the read process executes first, it will contain no data (and the count will be zero). If the write process execute first, it will contain some data.
问题在于获取写入管道的字节数。你在 fork() 之后就得到了它。如果读取过程首先执行,它将不包含任何数据(并且计数将为零)。如果写入过程首先执行,它将包含一些数据。
How to make child process wait till data is written on the other end?
如何让子进程等待数据写入另一端?
Since you opened the pipe in blocking mode, you should read as much data as possible, and not try to get the size of written data.
由于您以阻塞模式打开管道,因此您应该尽可能多地读取数据,而不是尝试获取写入数据的大小。
Here is your modified example that waits for a full message :
这是等待完整消息的修改示例:
#include <stdio.h>
#include <sys/ioctl.h>
int main()
{
int pid;
FILE *fp;
fp = fopen("test.txt","w");
char *buff = malloc(1024);
int fd[2];
int count = 0 ;
pipe(fd);
pid = fork();
if(pid == 0)
{
close(fd[1]);
int i = 0;
while ( i < 10 )
{
fprintf(fp,"\n TIME before read: %s \n",__TIME__);
read(fd[0], buff+i, 1);
++ i;
}
fprintf(fp,"Full message received!\nbuffer: %s\n TIME after read %s\n", buff, __TIME__);
}
else{
close(fd[0]);
sleep(10); //delay caused by application specific code replaced with sleep
write(fd[1],"THIS is it",10);
}
fclose(fp);
return 0;
}
回答by Nan Xiao
I think after
我想之后
ioctl(fd[0], FIONREAD, &count);
the count is 0.
read(fd[0], buff, count) will get no data.
try
read(fd[0], buff, 10)

