A Multi-Process Application
CS350
Create the following program consisting of n processes:
- Process 1:
- Computes the product (often called the cross-product) of two matrices, which are at least 3 by 3, by using FORKed copies of itself (Processes 2..n) to do the actual computations concurrently.
- Allocates space for the input matrices.
- Allocates space for the Processes to insert the values for the resulting matrix in dynamic (shared) storage (size determined at execution time, dependant on input matrices, when the data is input).
- JOINs with all 'n' copies of PROCESS 2.
- Prints out the resulting matrix in rows and columns
- Process 2..n:
- Accesses the shared memory and computes a set of results into the output matrix in shared memory, the address of which is initially set up by Process 1. Process 1 will accept these results for final printout.
- Each Process 2..n uses shared memory to access its own portion of the input matrices (there must be an indicator as to their size).
- JOINS process 1 after computing its own portion of the solution.
Hints:
- The shared memory can be dynamically obtained by using new, malloc, or any other language facility you choose and anchored with a local, static variable, BEFORE doing the FORK. But this memory, when modified, becomes PRIVATE to the modifier and the parent does not see it. To communicate back to the parent, shmget and shmat MUST be used.
- “waitpid” is the ATOMIC equivalent of the following code:
count=count-1; // count is a SHARED variable
if (count!=0) QUIT( ); // QUIT terminates the current process
3. Parent code:
for (index=1;index<max;index++)
childpid=fork();
Here's the clever part of this seemingly simple code:
The child inherits "index" at the LAST VALUE IT HAD when the fork occurred. Future changes to "index", in the loop, will NEVER be seen by the child, because it has ONLY knowledge of the parent's RAM at fork() time!! So now the child KNOWS its index number, and thus what pair to work on. You can even put the incoming matrices in NORMAL memory, BEFORE the fork(), because all pointers, and new/malloc'd memory, will be available to all children as of fork() time.
The only thing that REALLY needs to be in shared RAM is the ANSWERS from each child (and maybe some flags), because that's the only way the parent can get them. The parent may need to use join(), while the children may need to use exit(). You have to remember that the parent version of the code must be the last program standing, so you can get the answers.
Suggestions:
- First, determine the dimensions of the arrays to by multiplied.
- Determine the dimensions of the resulting array, so you will know how many copies of Process 2 will be needed and how much storage to allocate for the results form each Process 2..n.
- Allocate an array of pointers large enough to contain all the "handles" to the shared memory data for all the processes.
- Be sure all of the processes have been JOINed, before attempting to print a solution.
Additional:
· Test your program with AT LEAST TWO different sets of matrices, each set having DIFFERENT dimensions. The two sets should not both have square matrices, though ONE set may be square.
· Your input data (2 matrices) must be read from a file. The input consists of ONLY the values in the matrix. Your program must determine the size of each row and column from the number of values read. Input data should LOOK like a matrix. Separate the input matrices with a row of *'s. A printed copy of the input must be handed-in with your results. Output must be to BOTH a file and the console. The file must then be printed and handed-in.
The following is a general approach to the problem:
· Read the matrices into memory
· Allocate space in shared memory for answers. (shmget) Save results in ID (in normal RAM) for all the children to get at.
· Attach the shared memory to the parent (shmat)
o Compute the number of multiplies needed
o Define a vector or array for answers (one slot for each required multiply).
· Define 3 variables in regular (local) memory:
o Multiplier
o Multiplicand
o Index into vector or array defined above
o Pointer to the vector or array defined above
· Do the following loop:
Set the values of the local variables above, for the fork you are about to do.
(Remember that the child has full access to everything in local memory at the instant of the fork operation)
fork()
if child (return code from the fork was 0):
shmat using the ID saved above
multiply(multiplier, multiplicand) using the values in local memory
store answer in place indicated by “index”
exit
· End of loop
// only the parent can enter the following code (because of the "exit" above)
Join
Compute sums of array elements
Print answers
exit() or return
int multiply (a, b)
/* done here as a function to show how to allow for possibly more complex operations without having to mess with basic code in the main loop */
{ return (a*b);}
© D. J. Foreman, All rights reserved