[英]Why the parent process read only the first and sixth message from a child process?
我正在尝试从子进程向父进程发送十条消息。 但是程序的输出显示父进程仅读取第一条消息和第六条消息。 我试图更改代码中的sleep()位置,也尝试使用while()而不是for()进行读取,但是问题仍然相同。 这是代码:
int main(int argc, char *argv[]){
char ch, message_from_A[100], message_from_B[100], msg_to_log[100], msg_to_B[100];
int i, x, fd_log[2], fd_A_B[2], fd_B_C[2], fd_B_D[2];
pipe(fd_log);
//fork process A
if (fork()==0) { //child
printf("Inside process A\n");
for (i=0; i < 10; i++) {
//creat new msg
x = (rand() % 2);
if (x == 1)
ch='C';
else
ch='D';
//write msg to log pipe
sprintf(msg_to_log, "A sent to B: %c %d\n", ch, i);
printf("wirtten to log pipe--> %s\n", msg_to_log);
close(fd_log[READ]);
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
}//end for()
close(fd_log[WRITE]); //this line won't affect output
_exit(1);
} else { //parent
printf("Inside process log\n");
close(fd_log[WRITE]);
while ( read(fd_log[READ], message_from_A, 100) > 0 ) {
sleep(1);
printf("\nmsg from A: %s", message_from_A);
}
close(fd_log[READ]); //this line won't affect output
}}
该程序的输出显示父级仅读取第一条消息和第六条消息! 这是输出:
内部流程日志
内部流程A
要记录管道-> A发送到B:C 0
要记录管道-> A发送到B:C 1
要记录管道-> A发送到B:C 2
要记录管道-> A发送到B:D 3
想要记录管道-> A发送到B:D 4
要记录管道-> A发送到B:D 5
要记录管道-> A发送到B:D 6
要记录管道-> A发送到B:D 7
要记录管道-> A发送到B:C 8
要记录管道-> A发送到B:C 9
消息从A:A发送到B:C 0
来自A的消息:B:D 5
我感谢任何想法或建议。
在孩子中,您正在编写一些类似于以下内容的数据块:
A sent to B: C x
每个后跟一个空字符(上面的“ x”由表示写入管道的数据行的数字代替)。 但是,正在读取管道的进程将读取已放入管道的所有内容,直到read()
函数调用中指定的限制-它不会在null字符处停止。 因此,第一个read()
可能会从管道中的以下内容中获取前100个字符:
A sent to B: C 0\0A sent to B: C 1\0A sent to B: C 2\0A sent to B: C 3\0A sent to B: C 4\0A sent to B: C 5\0
但是,当父项显示从管道读取的内容时,它会将其打印为以空终止的字符串,因此仅显示缓冲区的第一部分。
然后,下一次读取将拾取保留在管道中的片段(以及该片段之后的所有内容),并再次显示仅直到空字符为止。
要解决此问题,请使用read()
的返回码找出返回的内容,并适当处理空字符。
罪魁祸首似乎是这条线:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
应该是:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log));
否则,您将发送一个额外的字符(它将为'\\0'
, msg_to_log
为全局msg_to_log
。)因此,即使read()
成功,它也不会打印整个字符序列(只打印'\\0'
) 。 此外memset
msg_to_log
每次在填充它之前(以确保没有旧的字符挂在那里)。 还要在每次打印后memset
message_from_A
(出于相同的原因)。
另外,移动close(fd_log[READ]);
在for循环之前。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.