|
#include <stdio.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <sys/types.h> |
|
#include <sys/wait.h> |
|
|
|
// select TEST 1 or 2. TEST=0 reads from stdin |
|
#ifndef DO_TEST |
|
#define DO_TEST 1 |
|
#endif |
|
#if DO_TEST > 0 |
|
const char *test_input1[] = { |
|
"2", // n |
|
"1", "2", // A |
|
"3", "4", |
|
"1", "2", // B |
|
"3", "4", |
|
}; |
|
|
|
const char *test_input2[] = { |
|
"2", // n |
|
"1", "0", // A |
|
"0", "1", |
|
"1", "0", // B |
|
"0", "1", |
|
}; |
|
|
|
#define INP(F, D) do { sscanf(*line, F, D); line++; } while (0) |
|
#else |
|
#define INP(F, D) scanf(F, D) |
|
#endif |
|
|
|
|
|
// Program Structure |
|
enum program_constants { max_dimension = 10 }; |
|
|
|
struct context { |
|
int max; |
|
int pfd[2]; // pipe |
|
pid_t pid[max_dimension]; // subprocesses |
|
int A[max_dimension][max_dimension]; |
|
int B[max_dimension][max_dimension]; |
|
int C[max_dimension][max_dimension]; |
|
}; |
|
|
|
static int init_context(struct context* C); |
|
static int start_jobs(struct context* C); |
|
static int read_result(struct context* C); |
|
|
|
|
|
// Program main |
|
int main(int argc, char* argv[]) |
|
{ |
|
struct context C; |
|
int err; |
|
if (0 != (err = init_context(&C))) { |
|
return err; |
|
} else if (0 != (err = start_jobs(&C))) { |
|
return err; |
|
} else if(0 != (err = read_result(&C))) { |
|
return err; |
|
} else { |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
// Functions |
|
int init_context(struct context* C) |
|
{ |
|
int i,j; |
|
|
|
#if DO_TEST == 1 |
|
const char** line = test_input1; |
|
#elif DO_TEST == 2 |
|
const char** line = test_input2; |
|
#endif |
|
printf("Enter the size (%d)", getpid() ); |
|
INP("%d", &C->max); |
|
if (0 < C->max && C->max < max_dimension) { |
|
for(i = 0;i < C->max; i++) |
|
{ |
|
printf("Enter row %d of your matrix A: ", i); |
|
for(j=0;j<C->max;j++) |
|
{ |
|
INP("%d",&C->A[i][j]); |
|
} |
|
} |
|
// Get input for the first matrix |
|
|
|
for(i = 0; i < C->max; i++) |
|
{ |
|
printf("Enter row %d of your matrix B: ", i); |
|
for(j=0;j<C->max;j++) |
|
{ |
|
INP("%d",&C->B[i][j]); |
|
} |
|
} |
|
// Get input for the second matrix |
|
printf("\n"); |
|
return 0; |
|
} else { |
|
return -1; // dimension must be in [1,max_dimension[ |
|
} |
|
} |
|
|
|
int start_jobs(struct context* C) |
|
{ |
|
int i; |
|
int comm[2]; |
|
|
|
if(pipe(C->pfd)==-1) |
|
{ |
|
fprintf(stderr,"Error\n"); |
|
exit(1); |
|
} |
|
|
|
for(i = 0; i < C->max; i++) |
|
{ |
|
C->pid[i]=fork(); |
|
if((C->pid[i])==0) |
|
{ |
|
int j, prod, c; |
|
printf("CHLD %i %d\n", i, getpid()); |
|
close(C->pfd[0]); |
|
for(j = 0; j < C->max; j++) |
|
{ |
|
prod=0; |
|
for(c = 0; c < C->max; c++) |
|
{ |
|
//printf("A: %d, B: %d\n", C->A[i][c], C->B[c][j]); |
|
prod += C->A[i][c]*C->B[c][j]; |
|
|
|
} |
|
printf("A_%d_S * B_S_%d = %d\n", i, j,prod); |
|
comm[0] = i; comm[1] = prod; |
|
write(C->pfd[1], comm, sizeof comm); |
|
} |
|
|
|
exit(0); |
|
} else if (C->pid[i] < 0) { |
|
return -1; // a fork failed |
|
} |
|
} |
|
return 0; // all processes started. |
|
} |
|
|
|
int read_result(struct context* C) |
|
{ |
|
int i, j, _k, k[max_dimension], finalprod; |
|
int status; |
|
int comm[2]; |
|
memset(k, 0, sizeof k); |
|
for(j = 0; j < C->max; j++) |
|
{ |
|
if(C->pid[j] != 0) |
|
{ |
|
for(_k = 0; _k < C->max; _k++) |
|
{ |
|
read(C->pfd[0], comm, sizeof comm); |
|
i = comm[0]; finalprod = comm[1]; |
|
C->C[k[i]][i] = finalprod; |
|
printf("C[%d][%d] = %d\n", k[i], i, C->C[k[i]][i]); |
|
++k[i]; |
|
} |
|
} |
|
} |
|
for(j = 0; j < C->max; j++) { |
|
waitpid(C->pid[j],&status,0); |
|
} |
|
return 0; |
|
} |
we need to move the
k
index in a row ordered way.