gpt4 book ai didi

c - 与管道的双向通信

转载 作者:行者123 更新时间:2023-12-03 09:51:29 25 4
gpt4 key购买 nike

我需要使用管道在父级和 fork 的子级之间创建通信。父进程将发送 0,子进程返回 1,父进程将回复 2,以此类推,直到计数器达到 5。然后两个进程都将终止。

我尝试使用两个管道来实现这一点:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
int fd[2];
int fd2[2];

int val = 0;

// create pipe descriptors
pipe(fd);
pipe(fd2);

// fork() returns 0 for child process, child-pid for parent process.
if (fork() != 0) {
///0. Send: 0
// parent: writing only, so close read-descriptor.
close(fd[0]);

// send the value on the write-descriptor.
val = 0;
resend:
write(fd[1], &val, sizeof(val));
printf("0.Parent(%d) send value: %d\n", getpid(), val);

// close the write descriptor
close(fd[1]);

///3. Receive 1;
close(fd2[1]);

// now read the data
read(fd2[0], &val, sizeof(val));
printf("3.Parent(%d) received value: %d\n", getpid(), val);

// close the read-descriptor
close(fd2[0]);
wait(NULL);
val++;
if (val < 6)
goto resend;
else
return 0;

} else { // child: reading only, so close the write-descriptor
childStart:
wait(NULL);

///1. receive: 0
close(fd[1]);

// now read the data (will block)
read(fd[0], &val, sizeof(val));
printf("1.Child(%d) received value: %d\n", getpid(), val);

// close the read-descriptor
//close(fd[0]);

///2. Send: 1
// parent: writing only, so close read-descriptor.
close(fd2[0]);

// send the value on the write-descriptor.
val = val + 1;
write(fd2[1], &val, sizeof(val));
printf("2.Child(%d) send value: %d\n", getpid(), val);

// close the write descriptor
close(fd2[1]);
if(val <5) {
wait(NULL);
goto childStart;
}
else
return 0;
}
///////////////////////////////////////////////////////////////////////////////////

return 0 ;
}

我得到以下输出:

0.Parent(120978) send value: 0
1.Child(120979) received value: 0
2.Child(120979) send value: 1
1.Child(120979) received value: 1
2.Child(120979) send value: 2
1.Child(120979) received value: 2
2.Child(120979) send value: 3
1.Child(120979) received value: 3
2.Child(120979) send value: 4
1.Child(120979) received value: 4
2.Child(120979) send value: 5
3.Parent(120978) received value: 1
0.Parent(120978) send value: 2
3.Parent(120978) received value: 2
0.Parent(120978) send value: 3
3.Parent(120978) received value: 3
0.Parent(120978) send value: 4
3.Parent(120978) received value: 4
0.Parent(120978) send value: 5
3.Parent(120978) received value: 5

如何让进程等待彼此的消息?

最佳答案

你的代码有很多问题,我改变了很多东西,结果是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>

int main(int argc, char *argv[])
{
int signo;
pid_t child_pid,parent_pid;
sigset_t newmask;
int fd[2];
int fd2[2];

int val = 0;

// create pipe descriptors
pipe(fd);
pipe(fd2);

// create mask for SIGUSR1
sigemptyset(&newmask);
sigaddset(&newmask,SIGUSR1);
sigaddset(&newmask,SIGUSR2);
sigprocmask(SIG_BLOCK,&newmask,NULL);

parent_pid = getpid();

// fork() returns 0 for child process, child-pid for parent process.
if ((child_pid = fork()) != 0) {
// Close unused file descriptors
close(fd[0]);
close(fd2[1]);

// send the value on the write-descriptor.
for(val = 0; val < 6; val++){
write(fd[1], &val, sizeof(val));
printf("0.Parent(%d) send value: %d\n", getpid(), val);
sigwait(&newmask,&signo);
kill(parent_pid,SIGUSR2);

// now read the data
read(fd2[0], &val, sizeof(val));
printf("3.Parent(%d) received value: %d\n", getpid(), val);
sigwait(&newmask,&signo);
kill(parent_pid,SIGUSR2);
}

return 0;

} else { // child: reading only, so close the write-descriptor
// Closing unused file descriptors
close(fd[1]);
close(fd2[0]);


for(; val <= 5; val++){
// now read the data (will block)
read(fd[0], &val, sizeof(val));
printf("1.Child(%d) received value: %d\n", getpid(), val);
kill(child_pid,SIGUSR1);
sigwait(&newmask,&signo);

// send the value on the write-descriptor.
write(fd2[1], &val, sizeof(val));
printf("2.Child(%d) send value: %d\n", getpid(), val);
kill(child_pid,SIGUSR1);
sigwait(&newmask,&signo);
}

wait(NULL);

return 0;
}
}

你的错误:
  • 您试图在关闭的文件描述符上写入
  • 您没有在 child 和 parent 之间创建任何类型的同步:
    为了创建这个,我使用了 sigwait() ( https://www.man7.org/linux/man-pages/man3/sigwait.3.html ) 和 kill ( https://www.man7.org/linux/man-pages/man2/kill.2.html ),
  • 您用过 wait(NULL)在 child 和其他无用的地方
  • 您创建了意大利面条式代码,这不是真正的错误,但不要使用 goto 而不是循环。

  • 输出:
    0.Parent(14956) send value: 0
    1.Child(14957) received value: 0
    2.Child(14957) send value: 0
    3.Parent(14956) received value: 0
    0.Parent(14956) send value: 1
    1.Child(14957) received value: 1
    2.Child(14957) send value: 1
    3.Parent(14956) received value: 1
    0.Parent(14956) send value: 2
    1.Child(14957) received value: 2
    2.Child(14957) send value: 2
    3.Parent(14956) received value: 2
    0.Parent(14956) send value: 3
    1.Child(14957) received value: 3
    2.Child(14957) send value: 3
    3.Parent(14956) received value: 3
    0.Parent(14956) send value: 4
    1.Child(14957) received value: 4
    2.Child(14957) send value: 4
    3.Parent(14956) received value: 4
    0.Parent(14956) send value: 5
    1.Child(14957) received value: 5
    2.Child(14957) send value: 5
    3.Parent(14956) received value: 5

    关于c - 与管道的双向通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61956074/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com