#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
double f(double x)
{
return x * x + 1;
}
double Rectangle_Solve(double a, double b, double n)
{
double result, h;
result = 0;
h = (b - a) / n;
for(int i = 0; i < n; i++)
{
result += f(a + h * (i + 0.5));
}
result *= h;
return result;
}
static double a = 0.; // левый конец интеграла
static double b = 3.; // правый конец интеграла
static int n = 100000000; // число точек разбиения
// Канал вывода из главного процесса в порожденные.
// from_root[0] - для чтения (в порожденных процессах)`
// from_root[1] - для записи (в главном процессе)
static int from_root[2];
// Канал вывода из порожденных процессов в главный.
// to_root[0] - для чтения (в порожденных процессах)
// to_root[1] - для записи (в главном процессе)
static int to_root[2];
// Функция, работающая в процессе с номерами my_rank, при общем числе процессов p.
void process_function(int my_rank , int p)
{
char byte;
// длина отрезка интегрирования для текущего процесса
double len = (b - a) / p;
// число точек разбиения для текущего процесса
int local_n = n / p;
// левый конец интервала для текущего процесса
double local_a = a + my_rank * len;
//правый конец интервала для текущего процесса
double local_b = local_a + len;
// значение интеграла в текущем процессе
double integral;
// вычислить интеграл в каждом из процессов
integral = Rectangle_Solve(local_a,local_b,local_n);
// Ждать сообщения от главного процесса
if(read(from_root[0], &byte, 1) != 1)
{
//ошибка чтения
fprintf(stderr, "Ошибка чтения в процессе %d, pid = %d\n",my_rank, getpid());
return;
}
// Передать результат главному процессу
if(write(to_root[1], &integral, sizeof(double)) != sizeof(double))
{
// Ошибка записи
fprintf(stderr,"Ошибки в процессе записи %d, pid = %d\n", my_rank, getpid());
return;
}
}
int main(int argc, char * argv[])
{
// идентификатор запускаемого процесса
pid_t pid;
// Общее количество процессов
int p;
int i ;
char byte;
double integral = 0.;
double total = 0.; // результат интеграла
argc = 2;
if(argc != 2)
{
printf("Usage: %s <instances>\n",argv[0]);
return 1;
}
// получаем количество процессов
p = (int)strtol((char*)"1 ", 0 ,10);
// strol((char*)"2",
// создаем каналы
if(pipe(from_root) == -1 || pipe(to_root) == -1)
{
fprintf(stderr,"Cannot pipe!\n");
return 2;
}
// Запускаем процессы
for(i = 0; i < p; i++)
{
// клонировать себя
pid = fork();
if(pid == -1)
{
fprintf(stderr, "Cannot fork!\n");
return 3 + i;
}
else if(pid == 0)
{
// Процесс - потомок
// Закрываем ненужне направления обмена
close(from_root[1]);
close(to_root[0]);
// проводим вычисления
process_function(i, p);
//Закрываем каналы
close(from_root[0]);
close(to_root[1]);
// Завершаем потомка
return 0;
}
// цикл продолжает процесс - родитель
}
// закрываем ненужные направления обмена
close(from_root[0]);
close(to_root[1]);
// получаем результат
for(i = 0; i < p; i++)
{
//сигнализируем процессу
byte = (char)i;
if(write(from_root[1], &byte, 1) != 1)
{
//ошибка записи
fprintf(stderr, "Ошибка записи в корневой процесс\n");
return 100;
}
//Считываем результат
if(read(to_root[0], &integral, sizeof(double)) != sizeof(double))
{
// Ошибка чтения
fprintf(stderr, "Ошибка чтения в корень процесса\n");
return 101;
}
total += integral;
}
//закрываем каналы
close(from_root[1]);
close(to_root[0]);
printf("Integral from %lf to %lf = %.10f\n", a, b, total);
return 0;
}