[英]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.