【发布时间】:2021-03-05 14:54:28
【问题描述】:
我最近研究了信号主题以及如何使用它们来帮助同步流程。我正在尝试写一些可以像乒乓球一样工作的东西。当有 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打印,每个进程只打印一个数字,然后加一。孙子打印出第一个数字。他首先打印 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;
}
}
【问题讨论】:
-
您实际上并没有描述该程序应该做什么。也就是说,这个任务的“乒乓”的正式定义是什么?示例输出很好,但您还需要描述程序的整体意图。另外,请描述您得到的结果,而不是预期的行为。
-
我审核过了,能否请您重新提出问题?
-
进程是无性别的。从来没有“儿子”,总是“孩子”。
-
如果您使用信号进行通信,那么您就违反了进程只能通过一个管道进行通信的条件。
-
好吧,这里只使用信号来同步输出队列,对于这种类型的连接来说,只有一个管道似乎就足够了,其中只有一个进程同时打印,增加整数并给出标记到队列中的下一个进程,为什么你认为违反了条件?
标签: c unix process signals posix