为什么父进程只读取来自子进程的第一条和第六条消息?

时间:2015-06-23 04:24:35

标签: c process fork parent-child

我正在尝试从子进程向父进程发送十条消息。但是程序的输出显示父进程只读取第一条和第六条消息。我试图改变代码中的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的消息

我感谢任何想法或建议。

2 个答案:

答案 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]);