为什么 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 编辑的内容,并适当处理空字符。