我正在尝试从子进程向父进程发送十条消息。但是程序的输出显示父进程只读取第一条和第六条消息。我试图改变代码中的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
记录管道 - &gt; A发送给B:C 0
记录管道 - &gt; A发送给B:C 1
记录管道 - &gt; A送到B:C 2
记录管道 - &gt; A送到B:D 3
记录管道 - &gt; A送到B:D 4
记录管道 - &gt; A送到B:D 5
记录管道 - &gt; A送到B:D 6
记录管道 - &gt; A发送给B:D 7
记录管道 - &gt; A送到B:C 8
记录管道 - &gt; A送到B:C 9
来自A的消息:A发送给B:C 0
来自A:B:D 5的消息
我感谢任何想法或建议。
答案 0 :(得分:3)
在孩子中,您正在编写几个看似如下的数据块:
A sent to B: C x
每个后跟一个空字符(上面的'x'被一个数字代替,表示写入管道的数据行)。但是,正在读取管道的进程将读取已放入管道的任何内容,直到read()
函数调用中指定的限制 - 它不会停止在空字符处。因此,第一个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()
中的返回代码来确定返回的内容,并适当处理空字符。
答案 1 :(得分:1)
这里的罪魁祸首似乎就是这句话:
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
是全局的)。因此,尽管read()
成功,但它不会打印整个字符序列(但只到'\0'
)。在每次填写之前memset
msg_to_log
也是如此(以确保没有任何旧字符挂在那里)。每次打印后也memset
message_from_A
(出于同样的原因)。
此外,在for循环之前移动close(fd_log[READ]);
。