[英]Creating pipes in C for inter process communication between multiple processes
[英]Synchronization of inter process communication between three relative processes
我最近研究了信号的主题以及如何使用它们来帮助同步进程。 我正在尝试写一些像乒乓一样工作的东西。 当有 2 个进程(父和子)时,我可以设法做到,我的代码工作得很好,但是当有 3 个进程(父、子和孙)时,它不起作用,我无法弄清楚我做错了什么,请检查我的代码并帮助我。 如果输入为 10,则输出应如下所示,程序在输入 10 时正常工作,但如果输入为 3、4、5、7、8、9 等,则它不起作用。
孙子 0
儿子 1
父亲 2
儿子 3
孙子 4
儿子 5
父亲 6
儿子 7
孙子 8
儿子 9
父亲 10
编辑:
程序应该做什么:程序中应该创建父/子进程和孙子进程。 这 3 个进程应该只使用一个管道相互通信。 程序等待用户输入正整数。 根据这个输入,这3个进程应该一一打印出一个从0开始的数字。例如,如果输入是10,那么这些进程应该打印从0到1,每个进程只打印一个数字,然后加1。 孙子打印出第一个数字。 他首先打印 0 并使用管道通道发送下一个数字来处理孩子。 进程子打印,将数字增加一并将其发送到父进程。 父进程打印数字,将其增加一并将其发送给子进程。 一直这样,直到其中之一达到用户输入的数字。
对于输入 1,3,5,7,9 我的程序打印到 2,4,6,8,10 包括这些数字,这是不正确的。 对于输入 4,8,我的程序打印到数字 4 和 8,但一直等待并且不返回任何内容。
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile int flag = 0;
void SigHandler(int s)
{
signal(SIGUSR1, SigHandler);
flag = 1;
}
int main()
{
pid_t pid;
int fd[2];
int count=0, countMax, queue=0;
scanf("%d",&countMax);
signal(SIGUSR1, SigHandler);
if(pipe(fd) < 0)
{
perror("pipe\n");
return 1;
}
if((pid=fork()) < 0)
{
perror("fork\n");
return 2;
}
else if(pid == 0)
{
//SON
pid = fork();
if(pid<0)
{
perror("fork\n");
return 3;
}
else if(pid == 0)
{
//GRANDSON
while(count < countMax)
{
if(!flag)
pause();
flag = 0;
read(fd[0], &count, sizeof(int));
printf("grandson %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
kill(getppid(), SIGUSR1);
}
close(fd[0]);
close(fd[1]);
return 0;
}
else
{
//SON
flag = 0;
kill(pid, SIGUSR1);
while(count < countMax)
{
if(!flag)
pause();
flag = 0;
read(fd[0], &count, sizeof(int));
printf("son %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
if(queue == 0)
{
kill(getppid(), SIGUSR1);
queue = 1;
}
else
{
kill(pid, SIGUSR1);
queue = 0;
}
}
close(fd[0]);
close(fd[1]);
return 0;
}
}
else
{
//FATHER
write(fd[1], &count, sizeof(int));
kill(pid,SIGUSR1);
fflush(stdout);
while(count < countMax)
{
if(count>=countMax)
raise(SIGINT);
if(!flag)
pause();
flag = 0;
read(fd[0], &count, sizeof(int));
printf("father %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
kill(pid, SIGUSR1);
}
close(fd[0]);
close(fd[1]);
return 0;
}
}
我在程序中添加了一些调试输出
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile int flag = 0;
void SigHandler(int s)
{
signal(SIGUSR1, SigHandler);
flag = 1;
}
int main()
{
pid_t pid;
int fd[2];
int count=0, countMax, queue=0;
setvbuf(stderr, NULL, _IONBF, 0);
printf("enter maximum count: ");
scanf("%d",&countMax);
signal(SIGUSR1, SigHandler);
if(pipe(fd) < 0)
{
perror("pipe\n");
return 1;
}
if((pid=fork()) < 0)
{
perror("fork\n");
return 2;
}
else if(pid == 0)
{
//SON
pid = fork();
if(pid<0)
{
perror("fork\n");
return 3;
}
else if(pid == 0)
{
//GRANDSON
while(count < countMax)
{
if(!flag)
{
fprintf(stderr, "@ grandchild pause\n");
pause();
}
flag = 0;
fprintf(stderr, "@ grandchild read (after pause)\n");
read(fd[0], &count, sizeof(int));
printf("grandson %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
fprintf(stderr, "@ grandchild signal child\n");
kill(getppid(), SIGUSR1);
}
fprintf(stderr, "@ grandchild done\n");
close(fd[0]);
close(fd[1]);
return 0;
}
else
{
//SON
flag = 0;
kill(pid, SIGUSR1);
while(count < countMax)
{
if(!flag)
{
fprintf(stderr, "- child pause\n");
pause();
}
flag = 0;
fprintf(stderr, "- child read (after pause)\n");
read(fd[0], &count, sizeof(int));
printf("son %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
if(queue == 0)
{
fprintf(stderr, "- child signal parent\n");
kill(getppid(), SIGUSR1);
queue = 1;
}
else
{
fprintf(stderr, "- child signal grandchild\n");
kill(pid, SIGUSR1);
queue = 0;
}
}
fprintf(stderr, "- child done\n");
close(fd[0]);
close(fd[1]);
return 0;
}
}
else
{
//FATHER
write(fd[1], &count, sizeof(int));
kill(pid,SIGUSR1);
fflush(stdout);
while(count < countMax)
{
if(count>=countMax)
{
fprintf(stderr, "# parent raise SIGINT\n");
raise(SIGINT);
}
if(!flag)
{
fprintf(stderr, "# parent pause\n");
pause();
}
flag = 0;
fprintf(stderr, "# parent read (after pause)\n");
read(fd[0], &count, sizeof(int));
printf("father %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
fprintf(stderr, "# parent signal child\n");
kill(pid, SIGUSR1);
}
fprintf(stderr, "# parent done\n");
close(fd[0]);
close(fd[1]);
return 0;
}
}
使用输入4
我得到这个输出:
enter maximum count: 4
# parent pause
- child pause
@ grandchild read (after pause)
grandson 0
@ grandchild signal child
@ grandchild pause
- child read (after pause)
son 1
- child signal parent
- child pause
# parent read (after pause)
father 2
# parent signal child
# parent pause
- child read (after pause)
son 3
- child signal grandchild
- child done
@ grandchild read (after pause)
grandson 4
@ grandchild signal child
@ grandchild done
如您所见,最后孩子已经离开了循环。 孙子尝试向将不再反应的子进程发送信号,并且父进程在pause
等待信号,但没有进程会向父进程发送信号。
此行为取决于输入值。
编辑
可以在 Tevfik Oğuzhan AKSOY 的回答中找到解决此处显示问题的原始程序的修改版本。
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile int flag = 0;
void SigHandler(int s)
{
signal(SIGUSR1, SigHandler);
flag = 1;
}
int main()
{
pid_t pid;
pid_t pidFather = getpid();
int fd[2];
int count=0, countMax, queue=0;
scanf("%d",&countMax);
signal(SIGUSR1, SigHandler);
if(pipe(fd) < 0)
{
perror("pipe\n");
return 1;
}
if((pid=fork()) < 0)
{
perror("fork\n");
return 2;
}
else if(pid == 0)
{
//SON
pid = fork();
if(pid<0)
{
perror("fork\n");
return 3;
}
else if(pid == 0)
{
//GRANDSON
while(count < countMax)
{
if(!flag)
{
pause();
}
flag = 0;
read(fd[0], &count, sizeof(int));
if(count<=countMax)
{
printf("grandson %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
kill(getppid(), SIGUSR1);
}
}
close(fd[0]);
close(fd[1]);
return 0;
}
else
{
//SON
flag = 0;
kill(pid, SIGUSR1);
while(count < countMax)
{
if(!flag)
{
pause();
}
flag = 0;
read(fd[0], &count, sizeof(int));
if(count<=countMax)
{
printf("son %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
if(queue == 0)
{
kill(getppid(), SIGUSR1);
queue = 1;
}
else if(queue != 0)
{
kill(pid, SIGUSR1);
queue = 0;
}
}
}
kill(getppid(), SIGUSR1);
close(fd[0]);
close(fd[1]);
return 0;
}
}
else
{
//FATHER
write(fd[1], &count, sizeof(int));
kill(pid,SIGUSR1);
fflush(stdout);
while(count < countMax)
{
if(!flag)
{
pause();
}
flag = 0;
read(fd[0], &count, sizeof(int));
if(count<=countMax)
{
printf("father %d\n", count++);
fflush(stdout);
write(fd[1], &count, sizeof(int));
kill(pid, SIGUSR1);
}
}
close(fd[0]);
close(fd[1]);
return 0;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.