【问题标题】:Why the parent process read only the first and sixth message from a child process?为什么父进程只读取子进程的第一条和第六条消息?
【发布时间】:2015-06-23 04:24:34
【问题描述】:

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

感谢任何想法或建议。

【问题讨论】:

    标签: c process fork parent-child


    【解决方案1】:

    在孩子中,您正在编写几个看起来像这样的数据块:

    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() 的返回码来确定返回的内容,并适当处理空字符。

    【讨论】:

      【解决方案2】:

      这里的罪魁祸首似乎是这一行:

      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() 成功,它也不会打印整个字符序列(但只有在 @ 987654326@)。在每次填写之前还要memsetmsg_to_log(以确保没有旧字符挂在那里)。每次打印后还要memsetmessage_from_A(出于相同的原因)。

      另外,将 close(fd_log[READ]); 移到 for 循环之前。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-30
        相关资源
        最近更新 更多