如何解决并非我的所有子进程都运行在 for 循环的末尾
我有一个项目,我需要在其中创建 N 个子进程并在它们之间进行选举。所以到目前为止我已经做了一个函数来生成随机数(对于选举,他们必须比较他们被赋予的数字,然后选出较低的数字)。然后,我坚持让他们与管道通信以比较数字。我的问题是只有我的第一个子进程运行这个 for 循环的结尾我真的不明白为什么。到目前为止,这是我的所有代码:
void comparerIdElection(int (*pipes)[2],int numProc)
{
for (int i = 0; i < NBPROC; ++i)
{
if (numProc!=i)
{
close(pipes[i][0]);
printf("je suis %d et je ferme la pipe [%d][0]\n",getpid(),i );
}else printf("je suis %d et je laisse la pipe [%d][0] \n",i );
if (numProc +1 != i)
{
close(pipes[i][1]);
printf("je suis %d et je ferme la pipe [%d][1]\n",i );
}else printf("je suis %d et je laisse la pipe [%d][1] \n",i );
}
//Generate a random number for my child process
int GenererIdElection ()
{
srand(time(NULL)^getpid()<<16);
return rand()%NBPROC;
}
int main(int argc,char const *argv[])
{
int N = NBPROC,idElection,numProc= -1;
int pere = getpid();
/*Creation du nombre de pipe adequat */
int pipes[N][2];
int pids[N];
/* Indique l'etat du processus C = Candidat,B =B battu,E = Elu*/
char etat ;
printf("le nombre de processus que je crée est : %d\n",N);
// Creation d'un nombre de N processus fils par le même pere
for (int i = 0; i < N; ++i)
{
if(getpid()==pere){
fork() ;
numProc ++ ;
}
}
if (getpid() != pere)
{
pids[numProc] = getpid();
etat = 'C';
while(etat == 67)
{
idElection = GenererIdElection();
printf("je suis %d et j'ai eu %d,mon num proc est %d \n",numProc);
comparerIdElection(pipes,numProc);
printf("hop\n");
etat ='B';
}
}
if (getpid()==pere)
{
/*On attend la fin de chaque processus
pour mettre un terme au processu pere*/
for (int i = 0; i < N; ++i)
{
wait(&pids[i]);
}
}
exit(0);
}
这是执行后会发生的情况(我翻译了所有 printf):
[终端][1]
编辑:由于缺乏声誉,我无法发布图片,因此我复制/面食:
我是 1854 我有 1,我的 numproc 是:0
我是 1854 我不关闭管道 [0][0]
我是 1854 我关闭 [0][1]
我是 1854 我关闭管道 [1][0]
我是 1854 我不关闭管道 [1][1]
我是 1854 我关闭管道 [2][0]
我是 1854 我关闭 [2][1]
跳
我是 1855 我有 1,我的 numproc 是:1
我是 1855 我关闭管道 [0][0]
我是 1855 我关闭 [0][1]
我是 1855 我不关闭管道 [1][0]
我是 1856 我有 1,我的 numproc 是:2
我是 1856 我关闭管道 [0][0]
我是 1856 我关闭 [0][1]
我是 1856 我关闭管道 [1][0]
NB : NBPROC = 3 在这种情况下,但不管数值是多少,除了第一个子进程外,它不起作用。
解决方法
我似乎对你的程序的行为有一个合理的解释。正如我在评论中已经指出的那样,程序中存在一个明显的缺陷,即未设置 int pipes[N][2];
最终会出现在 close()
API 中,实际上只是导致 {{1 }} 被退回,可能没有达到预期的效果。
至于程序的行为,可以通过检查数组 EBADF
中填充的实际值来解释。由于原始问题中没有明确设置这些值,因此这些值基本上是未定义的,但是...
让我们尝试使用以下方法将它们设置为更合理的值:
int pipes[N][2];
传入 0 产生输出:
int pipeVal = INT32_MIN;
if(argc == 2) {
pipeVal = atoi(argv[1]);
}
for(int i = 0; i < N; ++i) {
if(pipeVal != INT32_MIN) {
pipes[i][0] = pipes[i][1] = pipeVal;
}
printf("%d: Pipe pair %d-%d\n",getpid(),pipes[i][0],pipes[i][1]);
}
这似乎符合预期:fork 3 个最终会退出的进程。让我们用 1 的值试试
61962: Number of process is : 3
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61963: Election Id 0,numProc 0
61963: Exiting while-loop
61964: Election Id 0,numProc 1
61964: Exiting while-loop
61965: Election Id 0,numProc 2
61965: Exiting while-loop
现在这看起来很奇怪,因为没有一个进程真正退出 while 循环,但主程序成功终止。为了实际检查子程序的退出状态,我添加了以下代码:
62033: Number of process is : 3
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62034: Election Id 0,numProc 0
62035: Election Id 2,numProc 1
62036: Election Id 0,numProc 2
这是传入 1 作为参数的输出:
if (getpid()==pere)
{
/*On attend la fin de chaque processus
pour mettre un terme au processu pere*/
for (int i = 0; i < N; ++i)
{
errno = 0;
int stat_val;
wait(&stat_val);
#if DBG == 1
printf("%d: WIFEXITED(%d),WEXITSTATUS(%d),WIFSIGNALED(%d),WTERMSIG(%d),WIFSTOPPED(%d),WSTOPSIG(%d),WIFCONTINUED(%d)\n",WIFEXITED(stat_val),WEXITSTATUS(stat_val),WIFSIGNALED(stat_val),WTERMSIG(stat_val),WIFSTOPPED(stat_val),WSTOPSIG(stat_val),WIFCONTINUED(stat_val));
#endif
}
}
这个输出表明所有进程正常退出,没有被任何信号异常停止。
线索就在这些进程试图关闭的实际 62215: WIFEXITED(1),WEXITSTATUS(0),WIFSIGNALED(0),WTERMSIG(0),WIFSTOPPED(0),WSTOPSIG(0),WIFCONTINUED(0)
62215: WIFEXITED(1),WIFCONTINUED(0)
中。在 Linux 中(至少)一个进程一旦创建就有 3 个文件描述符,fd
有 0
,stdin
有 1
,stdout
有 2
.当 0 作为参数传递给程序时,进程最终会关闭无论如何都没有使用的 stderr
(stdin
),因此没有问题,它们退出 close(0)
并随后的while循环。当 1 作为参数传递给程序时,进程最终关闭 comparerIdElection()
(stdout
),因此任何应该写入输出的内容都不再出现在控制台上,但是它们仍然退出 close(1)
和随后的 while 循环,从而从每个进程中退出 comparerIdElection()
。
现在来到共享的实际程序,最终填充的实际值是什么是未指定的,但是如果即使数组中的 WIFEXITED(1)
N*2
之一设置为 1,应展示上述行为(传入 1),即,即使 fd
不会写入控制台,但进程确实退出了 while 循环并且主父进程能够成功等待过程。在我的 PC 上(我也怀疑在您的 PC 上),这些数组元素中至少一个的实际值始终设置为 1。
我的 Mac 上管道 fd 对的值:
printf
他们在 TryItOnline 上的价值:
61120: Pipe pair -296602944-32766
61120: Pipe pair 23978080-1
61120: Pipe pair 64-0
它们在 OnlineGDB 上的值(需要添加编译器标志 25090: Pipe pair 0-0
25090: Pipe pair 68079952-32708
25090: Pipe pair 1-0
):
-DNBPROC=3
无论 5612: Pipe pair 1505064448-32611
5612: Pipe pair 1507242440-32611
5612: Pipe pair 1-0
的值如何,此分析都应成立,因为在管道 NBPROC
中存在 1 之前,该进程将最终关闭自己的 fd
并表现出类似的行为。
这是一个完整的程序,其中包含一些可以通过传入 stdout
和一些 PID 标记来启用的检测,以确定哪个进程是来自 :
DBG=1
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。