#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
//каналы передачи: 0 читать, 1 писать
static int from_root[2];//родитель ->потомок
static int to_root[2];//потомок -> родитель
static double local_function(double *a, size_t n, int k, int p)//k - текущий процесс(0 - родитель, остальные малыши - потомки), p - кол-во процессоров
{
size_t i1 = k*n/p;//старт
size_t i2 = (k+1)*n/p;//финиш
size_t i;
double res = 0;
for (i = i1; i < i2; i++) {
res+=a[i];
}
return res;//частичная сумма от потомка
}
static void process_function(double *a, size_t n, int k, int p)
{
char byte;//отклик от родителя
double res = local_function(a, n, k, p);
if (read(from_root[0], &byte, 1) != 1) {
fprintf(stderr, "Error reading process %d, pid = %d\n", k, getpid());
return;
}
if (write(to_root[1], &res, sizeof(double))!= sizeof(double)) {
fprintf(stderr, "Error writing in process %d, pid = %d\n", k, getpid());
return;
}
}
int main(int argc, char *argv[]) {
pid_t pid;
int p;
size_t n;
size_t i;
double *a;
int k;
double res;
double total;
char byte;
if (argc != 3 || sscanf(argv[1], "%d", &p) != 1|| sscanf(argv[2], "%zu", &n) != 1|| p < 1) {
printf("Usage: %s p n\n", argv[0]);
return 1;
}
if (n == 0) {
printf("Res = 0\n");
return 0;
}
a = malloc(n * sizeof(double));
if (!a) {
perror("malloc");
return 1;
}
//чтобы не суммировать мусор
for (i = 0; i < n; i++) {
a[i] = 1.0;
}
//создаем каналы
if (pipe(from_root) == -1|| pipe(to_root) == -1) {
perror("pipe");
return 2;
}
//создание потомков
for (k = 1; k < p; k++) {
pid = fork();
if (pid == -1){
perror("fork");
abort();
}
if (pid == 0) {//потомки
close(from_root[1]);
close(to_root[0]);
process_function(a,n,k,p);
close(from_root[0]);
close(to_root[1]);
free(a);
return 0; //клон завершен
}
}
close(from_root[0]);
close(to_root[1]);
total = local_function(a,n,0,p);
for (k = 1; k < p; k++) {
byte = (char)k;
if (write(from_root[1], &byte, 1)!= 1) {
perror("write to child");
break;
}
if (read(to_root[0], &res, sizeof(double))!= sizeof(double)) {
perror("read from child");
break;
}
total+=res;
}
close(from_root[1]);
close(to_root[0]);
for (k = 1; k < p; k++) {
wait(NULL);
}//ждем завершения всех детишек
free(a);
printf("Res = %f\n", total);
return 0;
}