三个相关进程之间进程间通信的同步
Synchronization of inter process communication between three relative processes
我最近研究了信号主题以及如何使用它们来帮助同步进程。我正在尝试写一些像 Ping-Pong 一样工作的东西。当有 2 个进程(父进程和子进程)时,我可以设法做到这一点并且我的代码工作得很好但是当有 3 个进程(父进程、子进程和孙进程)时,它就不起作用而且我无法弄清楚我做错了什么,请检查我的代码并帮助我。如果输入为 10,则输出应如下所示,程序在输入 10 时正常工作,但如果输入为 3、4、5、7、8、9 等,则它不起作用
孙子 0
儿子 1
父亲 2
儿子 3
孙子 4
儿子 5
父亲 6
儿子 7
孙子 8
儿子 9
父亲 10
编辑:
程序应该做什么:程序中应该有created parent/child 和grandchild 进程。这 3 个进程应该只使用一个管道相互通信。程序等待用户输入正整数。根据这个输入,这3个进程一个一个打印出一个从0开始的数字。比如输入10,进程应该从0打印到1,每个进程只打印一个数字,然后加1。孙子打印出第一个数字。他首先打印 0 并使用管道通道将下一个数字发送给进程子进程。进程子进程打印,将数字加一并发送给父进程。父进程打印该数字,将其加一并将其发送给子进程。如此直到其中一个达到用户输入的数字。
对于输入 1、3、5、7、9,我的程序打印到 2、4、6、8、10,包括这些数字,这是不正确的。
对于输入 4,8,我的程序打印到数字 4 和 8,但一直在等待并且没有 return 任何东西。
#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
如您所见,最后 child 已经离开了循环。 grandchild 尝试向 child 发送信号,后者将不再反应,而 parent 正在等待 pause
中的信号,但没有进程会发送信号向 parent.
发送信号
此行为取决于输入值。
编辑
可在 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;
}
}
我最近研究了信号主题以及如何使用它们来帮助同步进程。我正在尝试写一些像 Ping-Pong 一样工作的东西。当有 2 个进程(父进程和子进程)时,我可以设法做到这一点并且我的代码工作得很好但是当有 3 个进程(父进程、子进程和孙进程)时,它就不起作用而且我无法弄清楚我做错了什么,请检查我的代码并帮助我。如果输入为 10,则输出应如下所示,程序在输入 10 时正常工作,但如果输入为 3、4、5、7、8、9 等,则它不起作用
孙子 0
儿子 1
父亲 2
儿子 3
孙子 4
儿子 5
父亲 6
儿子 7
孙子 8
儿子 9
父亲 10
编辑:
程序应该做什么:程序中应该有created parent/child 和grandchild 进程。这 3 个进程应该只使用一个管道相互通信。程序等待用户输入正整数。根据这个输入,这3个进程一个一个打印出一个从0开始的数字。比如输入10,进程应该从0打印到1,每个进程只打印一个数字,然后加1。孙子打印出第一个数字。他首先打印 0 并使用管道通道将下一个数字发送给进程子进程。进程子进程打印,将数字加一并发送给父进程。父进程打印该数字,将其加一并将其发送给子进程。如此直到其中一个达到用户输入的数字。
对于输入 1、3、5、7、9,我的程序打印到 2、4、6、8、10,包括这些数字,这是不正确的。 对于输入 4,8,我的程序打印到数字 4 和 8,但一直在等待并且没有 return 任何东西。
#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
如您所见,最后 child 已经离开了循环。 grandchild 尝试向 child 发送信号,后者将不再反应,而 parent 正在等待 pause
中的信号,但没有进程会发送信号向 parent.
此行为取决于输入值。
编辑
可在 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;
}
}