Интересно, что 55 - это сумма всех чисел от 1 до 10: это должно дать вам мгновенную подсказку:
pipe () создает канал, однонаправленный канал данных, который можно использовать для межпроцессного взаимодействия. Массив pipefd используется для возврата двух файловых дескрипторов, относящихся к концам канала. pipefd [0] относится к концу чтения канала. pipefd [1] относится к концу записи канала.
Обратите внимание, что хорошо: однонаправлено. Другими словами, падре считывает те же значения, которые он записал (отсюда и 55).
Обычно вы устанавливаете две трубы для двунаправленного трафика, по одному для каждого направления. Поэтому я удвоил число каналов, используя четные для падре-ребенку и нечетные для другого направления.
Кроме того, ваши дети продолжают работу с циклом Падре, тогда как они должны немедленно выйти из этого цикла, чтобы их значение i
было правильным. У вас есть выход из цикла, основанный на padre
, но это происходит после изменения i
. Вы можете разбить, где вы установили padre
в false или просто i--
в бите if(!padre)
, чтобы восстановить i
в правильное значение для этого потомка. Я сделал последнее.
Следующий код (с маркерами, показывающими, что изменилось) работает нормально:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <math.h>
#define N 10
int main(int argc, char** argv)
{
pid_t figli[N];
unsigned int i;
int status;
int fd[N*2][2]; // CHANGED: two unidirectional pipes
int msg1=0,msg2;
int risultato=0;
bool padre=true;
for(i=0;i<N && padre;i++)
{
pipe(fd[i*2]);
pipe(fd[i*2+1]); // ADDED: create second pipe
figli[i]=fork();
if(figli[i]<0)
{
fprintf(stderr,"Una fork ha fallito\n");
}
else if(figli[i]==0)
{
padre=false;
}
else
{
msg1=i+1;
write(fd[i*2][1],&msg1,sizeof(int)); // CHANGED: pipe number
}
}
if(!padre)
{
i--; // ADDED: to restore i for the child
read(fd[i*2][0],&msg2,sizeof(int)); // CHANGED: pipe number
msg2=pow(2.0,msg2);
write(fd[i*2+1][1],&msg2,sizeof(int)); // CHANGED: pipe number
exit(0);
}
else
{
for(i=0;i<N;i++)
{
read(fd[i*2+1][0],&msg2,sizeof(int)); // CHANGED: pipe number
risultato+=msg2;
}
}
if(padre)
fprintf(stderr,"%d\n",risultato);
return 0;
}
Это дает правильный ответ 2046, начиная с 2<sup>0</sup> + 2<sup>1</sup> + ... 2<sup>10</sup> = 2<sup>11</sup> - 1
и, так как вы опускаете член с нулем (равный 1): 2<sup>1</sup> + 2<sup>2</sup> + ... 2<sup>10</sup> is 2<sup>11</sup> - 2 (2<sup>11</sup> = 2048)
.