我正在用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;
}
如何让子进程等到数据写入另一端?
答案 0 :(得分:5)
您的管道在阻止模式下打开,您无需更改它,这可能是您的意图。
但是,由于您要做的第一件事就是请求管道上等待的数据大小,然后盲目地跳转到读取那么多字节(在代码执行时很可能是零,因为父代没有写了任何东西)你不会阻止,而只是因为你没有要求而离开。
有很多方法可以做到这一点,包括选择循环。如果您希望阻止进行读取,直到数据可用,则在单个字节上执行此操作,然后填写剩余数据。
这绝不是如何执行 right 的示例,但它是如何等待单个字节,请求管道的读取大小的简短示例其余的数据,读取它,并继续这个,直到管道没有数据,父节点关闭它们的结束:
我希望你觉得它很有帮助。
#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;
}
<强>输出强>
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.
答案 1 :(得分:1)
问题在于获取写入管道的字节数。你在fork()之后得到它。如果首先执行读取过程,则它将不包含任何数据(并且计数将为零)。如果写入进程首先执行,它将包含一些数据。
如何让子进程等到数据写入另一端?
由于您在阻塞模式下打开了管道,因此您应该尽可能多地读取数据,而不是尝试获取写入数据的大小。
以下是等待完整消息的修改示例:
#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;
}
答案 2 :(得分:1)
我认为
之后ioctl(fd[0], FIONREAD, &count);
the count is 0.
read(fd[0], buff, count) will get no data.
try
read(fd[0], buff, 10)