Reputation: 111
I am trying to create multiple process by fork()
and do some mathematical operation on child process like sum of array elements and then return the values to parent process and parent will save each value in parentArray
as mention in code.
Now my problem is how to do this at this stage i am receiving only one value of first process the rest of values are zero. Is there is another way of passing value or it can be done uaing pipe?? Please help meππ
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
void showReturnStatus(pid_t childpid,int status){
if (WIFEXITED(status) && !WEXITSTATUS(status))
printf("Child %ld terminated normally\n", (long)childpid);
else if (WIFEXITED(status))
printf("Child %ld terminated with return status %d\n",(long)childpid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Child %ld terminated due to uncaught signal %d\n",(long)childpid, WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("Child %ld stopped due to signal %d\n",(long)childpid, WSTOPSIG(status));
}
int main(int argc, char *argv[])
{
srand(time(0));
int arraySize=9,noProcess=3,array[arraySize],status=0;
pid_t pid;
int parentSum=0;
int parentArray[3],fd[2]; //fd file descriptor
if(pipe(fd)==-1)
return 0;
for(int i=0 ;i<arraySize;i++)
array[i]=(rand()%100)+1;
for(int i=0;i<arraySize;i++){
printf("\n %d : %d ",i,array[i]);
}
printf("\nParent PID[%d] \n",getpid());
for(int childP=0;childP<noProcess;childP++){
int child=fork();
int childSum;
if(child==0){
close(fd[0]);
childSum=0.0;
for(int i=childP*3;i<(childP+1)*3;i++)
childSum+=array[i];
printf("\nChild Process No [%d] PID [%d] Return Sum : %d \n",childP,getpid(),childSum);
write(fd[1],&childSum,sizeof(childSum));
close(fd[1]);
exit(0);
}
pid=wait(&status);
showReturnStatus(pid,status);
close(fd[1]);
read(fd[0],parentArray,sizeof(parentArray));
close(fd[0]);
}
for (int i=0;i<3;i++)
{
printf("\nValue Array : %d\n",parentArray[i]);
}
printf("\nParent Process with PID [%d] calculate Sum : %d\n",getppid());
return 0;
}
Upvotes: 0
Views: 1538
Reputation: 754060
Here's a revised version of your code with multiple changes.
It lets the child processes run concurrently.
It pays attention to various error conditions.
It prints the data 10 entries per line.
It has a check that the array size is an integer multiple of the number of processes.
It does not close the pipe prematurely in the parent.
It reports errors to standard error, and exits with a failure status.
It prints newlines at the end of output messages; it does not need to print newlines at the start of the messages.
I prefer to avoid noProcess
as it suggests 'no process'; I renamed it numProcess
.
The code uses numProcess
and arraySize
to control all the relevant loops, etc.
It calculates and prints the sum in the parent process so that the values from the children can be checked quickly. This also shows that using processes is an artefact for the purposes of this exercise.
It prints the array with multiple entries per line.
I adjusted the calculation to generate numbers 1..99 so that format %2d
works uniformly.
I compile with these options (source code pipe79.c
, program pipe79
):
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe79.c -o pipe79
The test for argc > 0
is just to ensure that argc
is used β if it isn't, the code fails to compile because of the unused variable.
I introduced variables numPerProcess
and start
and stop
because the values are used at least twice.
I didn't need to touch showReturnStatus()
beyond making it static, which again is necessary because of the compilation options I use. The function isn't used outside this source file, so IMO it should be static
anyway. If it was used elsewhere, it would be declared in a header which would be included both where it is defined and where it is used.
It's likely there are other detailed changes that could be pointed out but I've forgotten that I made the change.
Code:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static void showReturnStatus(pid_t childpid, int status)
{
if (WIFEXITED(status) && !WEXITSTATUS(status))
printf("Child %ld terminated normally\n", (long)childpid);
else if (WIFEXITED(status))
printf("Child %ld terminated with return status %d\n", (long)childpid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Child %ld terminated due to uncaught signal %d\n", (long)childpid, WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("Child %ld stopped due to signal %d\n", (long)childpid, WSTOPSIG(status));
}
int main(int argc, char *argv[])
{
srand(time(0));
int arraySize = 72;
int numProcess = 6;
int array[arraySize];
int fd[2];
const char *arg0 = (argc == 0) ? "pipe79" : argv[0]; /* Use argc */
assert(arraySize % numProcess == 0);
int numPerProcess = arraySize / numProcess;
if (pipe(fd) == -1)
{
fprintf(stderr, "%s: failed to create a pipe\n", arg0);
exit(EXIT_FAILURE);
}
int sum = 0;
for (int i = 0; i < arraySize; i++)
{
array[i] = (rand() % 99) + 1;
sum += array[i];
}
int width = 0;
const char *pad = "";
for (int i = 0; i < arraySize; i++)
{
width += printf("%s%2d: %2d", pad, i, array[i]);
pad = ", ";
if (width > 72)
{
putchar('\n');
width = 0;
pad = "";
}
}
if (width > 0)
putchar('\n');
printf("Sum calculated by parent: %d\n", sum);
printf("Parent PID[%d]\n", getpid());
for (int childP = 0; childP < numProcess; childP++)
{
int child = fork();
if (child < 0)
{
fprintf(stderr, "%s: failed to fork child %d\n", arg0, childP + 1);
exit(EXIT_FAILURE);
}
if (child == 0)
{
close(fd[0]);
int childSum = 0;
int start = childP * numPerProcess;
int stop = start + numPerProcess;
printf("Child PID %d: processing rows %d..%d\n", getpid(), start, stop - 1);
for (int i = start; i < stop; i++)
childSum += array[i];
printf("Child Process No [%d] PID [%d] Return Sum : %d\n", childP, getpid(), childSum);
if (write(fd[1], &childSum, sizeof(childSum)) != sizeof(childSum))
{
fprintf(stderr, "Child Process No [%d] PID [%d] failed to write to the pipe\n",
childP, getpid());
exit(EXIT_FAILURE);
}
close(fd[1]);
exit(0);
}
}
close(fd[1]);
sum = 0;
pid_t pid;
int status = 0;
while ((pid = wait(&status)) != -1)
{
int number;
showReturnStatus(pid, status);
if (read(fd[0], &number, sizeof(number)) != sizeof(number))
{
fprintf(stderr, "%s: parent process got a short read on the pipe\n", arg0);
exit(EXIT_FAILURE);
}
printf("sum from pipe: %d\n", number);
sum += number;
}
printf("Parent Process with PID [%d] accumulated sum : %d\n", getpid(), sum);
return 0;
}
Sample output:
0: 68, 1: 13, 2: 74, 3: 37, 4: 88, 5: 4, 6: 73, 7: 94, 8: 2, 9: 71
10: 20, 11: 19, 12: 93, 13: 96, 14: 13, 15: 96, 16: 98, 17: 12, 18: 94, 19: 10
20: 27, 21: 38, 22: 48, 23: 14, 24: 18, 25: 50, 26: 61, 27: 15, 28: 88, 29: 41
30: 2, 31: 99, 32: 42, 33: 8, 34: 55, 35: 32, 36: 29, 37: 53, 38: 78, 39: 15
40: 69, 41: 19, 42: 85, 43: 78, 44: 3, 45: 59, 46: 96, 47: 37, 48: 35, 49: 95
50: 59, 51: 12, 52: 63, 53: 34, 54: 31, 55: 17, 56: 88, 57: 63, 58: 74, 59: 15
60: 10, 61: 38, 62: 24, 63: 27, 64: 70, 65: 64, 66: 40, 67: 43, 68: 87, 69: 82
70: 35, 71: 11
Sum calculated by parent: 3451
Parent PID[58056]
Child PID 58057: processing rows 0..11
Child Process No [0] PID [58057] Return Sum : 563
Child PID 58058: processing rows 12..23
Child Process No [1] PID [58058] Return Sum : 639
Child PID 58059: processing rows 24..35
Child Process No [2] PID [58059] Return Sum : 511
Child PID 58060: processing rows 36..47
Child Process No [3] PID [58060] Return Sum : 621
Child PID 58061: processing rows 48..59
Child Process No [4] PID [58061] Return Sum : 586
Child 58059 terminated normally
sum from pipe: 563
Child 58060 terminated normally
sum from pipe: 639
Child 58058 terminated normally
sum from pipe: 511
Child 58057 terminated normally
sum from pipe: 621
Child 58061 terminated normally
sum from pipe: 586
Child PID 58062: processing rows 60..71
Child Process No [5] PID [58062] Return Sum : 531
Child 58062 terminated normally
sum from pipe: 531
Parent Process with PID [58056] accumulated sum : 3451
Upvotes: 1