Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么父进程只从子进程读取第一条和第六条消息?_C_Process_Fork_Parent Child - Fatal编程技术网

C 为什么父进程只从子进程读取第一条和第六条消息?

C 为什么父进程只从子进程读取第一条和第六条消息?,c,process,fork,parent-child,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

我正在尝试从子进程向父进程发送十条消息。但是程序的输出显示父进程只读取第一条和第六条消息。我尝试更改代码中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
}}
intmain(intargc,char*argv[]){
char ch、消息_from_A[100]、消息_from_B[100]、消息_to_log[100]、消息_to_B[100];
int i,x,fd_log[2],fd_A_B[2],fd_B_C[2],fd_B_D[2];
管道(fd_日志);
//分叉过程A
如果(fork()==0){//child
printf(“内部进程A\n”);
对于(i=0;i<10;i++){
//创造新的味精
x=(rand()%2);
如果(x==1)
ch='C';
其他的
"D",;
//将消息写入日志管道
sprintf(消息发送到日志,“A发送到B:%c%d\n”,ch,i);
printf(“wirtten-to-log管道-->%s\n”,msg\u-to\u-log);
关闭(fd_日志[读取]);
写入(fd_log[write],msg_to_log,strlen(msg_to_log)+1);
}//结束()
关闭(fd_log[WRITE]);//此行不会影响输出
_出口(1);
}else{//parent
printf(“内部过程日志”);
关闭(fd_日志[写入]);
while(读取(fd_日志[read],来自_A的消息,100)>0){
睡眠(1);
printf(“\nmsg来自A:%s”,消息来自A);
}
关闭(fd_log[READ]);//此行不会影响输出
}}
此程序的输出显示父级仅读取第一条和第六条消息!这是输出:

内部进程日志

内部进程A

wirtten到日志管道-->A发送到B:C 0

Wirten到日志管道-->A发送到B:C 1

Wirten到日志管道-->A发送到B:C 2

Wirten到日志管道-->A发送到B:D 3

Wirten到日志管道-->A发送到B:D 4

Wirten到日志管道-->A发送到B:D 5

Wirten到日志管道-->A发送到B:D 6

Wirten到日志管道-->A发送到B:D 7

Wirten到日志管道-->A发送到B:C 8

Wirten到日志管道-->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));
否则您将发送一个额外的字符(将是
'\0'
msg\u to\u log
为全局字符)。。因此,即使
read()
成功,它也不会打印整个字符序列(只有在
'\0'
之前)。在每次填充之前,也要将
memset
msg_to_log
(确保没有旧字符挂在那里)。此外,每次打印后(出于相同的原因),还会收到来自A的
memset
消息


另外,移动
close(fd_log[READ])在for循环之前

这里的罪魁祸首似乎是这样的:

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\u to\u log
为全局字符)。。因此,即使
read()
成功,它也不会打印整个字符序列(只有在
'\0'
之前)。在每次填充之前,也要将
memset
msg_to_log
(确保没有旧字符挂在那里)。此外,每次打印后(出于相同的原因),还会收到来自A的
memset
消息


另外,移动
close(fd_log[READ])在for循环之前

在子对象中,您正在写入多个数据块,这些数据块看起来像:

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
但是,当父级显示从管道读取的内容时,它会将其打印为以null结尾的字符串,因此只显示缓冲区的第一部分

然后,下一次读取将拾取留在管道中的片段(以及该片段之后的任何内容),并再次仅显示到空字符为止


要解决此问题,请使用
read()
中的返回代码来找出返回的内容,并适当地处理空字符。

在子级中,您正在写入几个类似以下内容的数据块:

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
但是,当父级显示从管道读取的内容时,它会将其打印为以null结尾的字符串,因此只显示缓冲区的第一部分

然后,下一次读取将拾取留在管道中的片段(以及该片段之后的任何内容),并再次仅显示到空字符为止

要解决此问题,请使用
read()
中的返回代码来确定返回的内容,并适当处理空字符