为什么 parent 进程只读取来自 child 进程的第一条和第六条消息?
Why the parent process read only the first and sixth message from a child process?
我正在尝试从 child 进程向 parent 发送十条消息。但是程序的输出显示 parent 进程只读取了第一条和第六条消息。我试图改变代码中 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
}}
这个程序的输出显示 parent 只读取了第一条和第六条消息!这是输出:
内部进程日志
内部进程 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 的消息
我很感激任何想法或建议。
这里的罪魁祸首似乎是这一行:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
应该是:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log));
否则你将发送一个额外的字符(这将是 '[=12=]'
,msg_to_log
是全局的)。因此即使 read()
成功,它也不会打印整个序列字符数(但仅限于 '[=12=]'
)。在每次填写之前还要 memset
msg_to_log
(以确保 none 的旧字符挂在那里)。每次打印后 memset
message_from_A
(出于同样的原因)。
此外,将 close(fd_log[READ]);
移到 for 循环之前。
在 child 中,您正在编写几个类似于以下内容的数据块:
A sent to B: C x
每个后跟一个空字符(上面的 'x' 被一个数字代替,表示写入管道的数据行)。然而,正在读取管道的进程将读取已放入管道中的所有内容,直到达到 read()
函数调用中指定的限制 - 它不会在空字符处停止。所以第一个 read()
可能会从管道中的以下内容中获取前 100 个字符:
A sent to B: C 0[=11=]A sent to B: C 1[=11=]A sent to B: C 2[=11=]A sent to B: C 3[=11=]A sent to B: C 4[=11=]A sent to B: C 5[=11=]
但是,当 parent 显示从管道读取的内容时,它会将其打印为空终止字符串,因此仅显示缓冲区的第一部分。
然后下一次读取将拾取留在管道中的片段(以及该片段之后的任何内容),并再次仅显示直到空字符。
要解决此问题,请使用 read()
中的 return 代码找出已 return 编辑的内容,并适当处理空字符。
我正在尝试从 child 进程向 parent 发送十条消息。但是程序的输出显示 parent 进程只读取了第一条和第六条消息。我试图改变代码中 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
}}
这个程序的输出显示 parent 只读取了第一条和第六条消息!这是输出:
内部进程日志
内部进程 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 的消息
我很感激任何想法或建议。
这里的罪魁祸首似乎是这一行:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
应该是:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log));
否则你将发送一个额外的字符(这将是 '[=12=]'
,msg_to_log
是全局的)。因此即使 read()
成功,它也不会打印整个序列字符数(但仅限于 '[=12=]'
)。在每次填写之前还要 memset
msg_to_log
(以确保 none 的旧字符挂在那里)。每次打印后 memset
message_from_A
(出于同样的原因)。
此外,将 close(fd_log[READ]);
移到 for 循环之前。
在 child 中,您正在编写几个类似于以下内容的数据块:
A sent to B: C x
每个后跟一个空字符(上面的 'x' 被一个数字代替,表示写入管道的数据行)。然而,正在读取管道的进程将读取已放入管道中的所有内容,直到达到 read()
函数调用中指定的限制 - 它不会在空字符处停止。所以第一个 read()
可能会从管道中的以下内容中获取前 100 个字符:
A sent to B: C 0[=11=]A sent to B: C 1[=11=]A sent to B: C 2[=11=]A sent to B: C 3[=11=]A sent to B: C 4[=11=]A sent to B: C 5[=11=]
但是,当 parent 显示从管道读取的内容时,它会将其打印为空终止字符串,因此仅显示缓冲区的第一部分。
然后下一次读取将拾取留在管道中的片段(以及该片段之后的任何内容),并再次仅显示直到空字符。
要解决此问题,请使用 read()
中的 return 代码找出已 return 编辑的内容,并适当处理空字符。