0

I am reading from the user the size of an arr. I create the arr[row][col] and fill it with random integers. Then i want to send each row from the parent process to the child so i create a new arr2 to store every time the current row in it. I read the arr2 to child process and calculating the sum of the row. At the end i want to send the sum to parent process and print it. I do this in a for(i=0;i<row;i++). The problem is that the child process only takes the first row every time.

#include <sys/types.h>
#include<stdio.h>
#include <unistd.h>
#include<time.h>
#include<stdlib.h>

int main(){

int gram, steiles;

printf("Dwse mou tis grammes tou pinaka\n");
scanf("%d", &gram);
printf("Dwse mou tis steiles tou pinaka\n");
scanf("%d", &steiles);

int arr[gram][steiles];
int arr2[gram];

srand(time(NULL));

for (int i = 0; i < gram; i++) {
  for (int j = 0; j < steiles; j++) {
    arr[i][j] = rand() % 20 + 1;
  }
}

for (int i = 0; i < gram; i++) {
  for (int j = 0; j < steiles; j++) {
    printf("%d", arr[i][j]);
    printf("\t");
  }
  printf("\n");
}
pid_t pid;
int fd[2], fd1[2], sum=0;

if (pipe(fd) == -1) {
  return 2;
}
if (pipe(fd1) == -1) {
  return 3;
}

    for (int i = 0; i < gram; i++) {
      pid = fork();
    
      if (pid<0) {
        return 1;
      }
    
      if (pid>0){   
        for (int j = 0; j < steiles; j++) {
          arr2[j]=arr[i][j];
        }
    
        close(fd[0]);
        write(fd[1], arr2, sizeof(int)*steiles);
        close(fd[1]);
    
        close(fd1[1]);
        read(fd1[0], &sum, sizeof(int));
        close(fd1[0]);
        printf("the sum of the row is: %d", sum);
    
    
      }else{ 
        wait(NULL);
        close(fd[1]);
        read(fd[0], arr2, sizeof(int)* steiles);
        close(fd[0]);
        for (int k = 0; k < steiles; k++) {
          // printf("%d\t", arr2[k]);
          sum+=arr2[k];
        }
        close(fd1[0]);
        write(fd1[1], &sum, sizeof(int));
        close(fd1[1]);
      }
}
}
fesoy96
  • 11
  • 4
  • Welcome to Stack Overflow. Please read the [About] and [Ask] pages. More urgently, please read about hot to create an MCVE ([Minimal, Complete, Verifiable Example](https://stackoverflow.com/help/mcve) — or MRE or whatever name SO now uses) or an SSCCE ([Short, Self-Contained, Correct Example](http://sscce.org/)) — the same idea by a different name. – Jonathan Leffler Feb 01 '22 at 15:13
  • The `wait(NULL);` in the child code (`else`) is pointless; newly created processes don't have children. – Jonathan Leffler Feb 01 '22 at 15:14
  • 1
    Note that after `fork()`, the child process is an exact copy of the parent, so there's really no need to write data out and then read it in again... the child already has access to a copy of the parent's data. – Caleb Feb 01 '22 at 15:16
  • In the child code, you don't limit the scope of `sum` to the `else` block, and you don't show that it is set to 0. You should define variables as close to where you use them as possible. You don't show that you validate any of the I/O operations; you should. – Jonathan Leffler Feb 01 '22 at 15:17
  • Are you making a mistake in the 'random initialization' of the array? For example, you should [only call `srand()` once](https://stackoverflow.com/q/7343833/15168). – Jonathan Leffler Feb 01 '22 at 15:19
  • I am testing it with a 2x2 array. I print it before fork and it works fine with random integers. Lets say the array is {2,4,7,8} the code will print four times: the sum of row is 6. I am using pipes cause this is an exercise and it says that we need to use pipes. – fesoy96 Feb 01 '22 at 15:25
  • And that's the reason why we want a [MRE] — we can't see what you're doing elsewhere. It's hard enough to debug your code with it all present; it is even harder with code missing! But do note the word ***minimal***. You can hard-wire the matrix sizing; you can even hard-wire the array initialization. But that lets us see what the problems aren't. – Jonathan Leffler Feb 01 '22 at 15:30
  • I did not added it cause i thought that code section would be too big. I am editing now. Thanks. – fesoy96 Feb 01 '22 at 15:33
  • You're using a single pair of pipes to connect to all the children, rather than separate pipes for each child? That can lead to race conditions. Also note the requirements for an MRE to show the input data and the expected and actual outputs. – Jonathan Leffler Feb 01 '22 at 15:34
  • Note that you should be defining `int arr2[steiles];` rather than `int arr2[gram];`. You'll be OK while `gram >= steiles` and you're probably testing with `gram == steiles`. – Jonathan Leffler Feb 01 '22 at 15:40
  • The parent process closes the pipes for the first child; the second and subsequent children don't stand a chance, poor things. They've been deprived of all communication with the parent, and you know how much children benefit from talking with their parents. Create the pipes inside the loop, not outside. Note that error checking the I/O calls would have told you about this problem. Don't forget to end messages with newlines. – Jonathan Leffler Feb 01 '22 at 15:46
  • Also, make sure your child processes exit after they've done their stuff. As it stands, the first child reads its data, and then goes back around the loop to run a new child (as well as the parent running a new child). – Jonathan Leffler Feb 01 '22 at 15:52

1 Answers1

0

I've outlined many of the problems in the comments above, including:

  • You don't error check your I/O calls but should.
  • The parent process closes the pipes for the first child; the second and subsequent children don't stand a chance, poor things. They've been deprived of all communication with the parent, and you know how much children benefit from talking with their parents.
  • Create the pipes inside the loop, not outside. Note that error checking the I/O calls would have told you about this problem.
  • Don't forget to end messages with newlines.
  • Also, make sure your child processes exit after they've done their stuff. As it stands, the first child reads its data, and then goes back around the loop to run a new child (as well as the parent running a new child).

Here's some code which still skips on the I/O error checking but works correctly:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

static void dump_vector(const char *tag, size_t size, const int *data);

int main(void)
{
    int gram, steiles;

    printf("Dwse mou tis grammes tou pinaka\n");
    scanf("%d", &gram);
    printf("Dwse mou tis steiles tou pinaka\n");
    scanf("%d", &steiles);

    int arr[gram][steiles];
    int arr2[gram];

    srand(time(NULL));

    for (int i = 0; i < gram; i++)
    {
        for (int j = 0; j < steiles; j++)
        {
            arr[i][j] = rand() % 20 + 1;
        }
    }

    for (int i = 0; i < gram; i++)
    {
        for (int j = 0; j < steiles; j++)
        {
            printf("%d", arr[i][j]);
            printf("\t");
        }
        printf("\n");
    }

    for (int i = 0; i < gram; i++)
    {
        pid_t pid;
        int fd1[2], fd2[2];

        if (pipe(fd1) == -1)
        {
            return 2;
        }
        if (pipe(fd2) == -1)
        {
            return 3;
        }
        pid = fork();

        if (pid < 0)
        {
            return 1;
        }

        if (pid > 0)
        {
            for (int j = 0; j < steiles; j++)
            {
                arr2[j] = arr[i][j];
            }

            dump_vector("arr2 - parent", steiles, arr2);

            close(fd1[0]);
            write(fd1[1], arr2, sizeof(int) * steiles);
            close(fd1[1]);

            int sum = 0;
            close(fd2[1]);
            read(fd2[0], &sum, sizeof(int));
            close(fd2[0]);
            printf("the sum of the row is: %d\n", sum);
        }
        else
        {
            close(fd1[1]);
            read(fd1[0], arr2, sizeof(int) * steiles);
            close(fd1[0]);
            dump_vector("arr2 - child", steiles, arr2);
            int sum = 0;
            for (int k = 0; k < steiles; k++)
            {
                // printf("%d\t", arr2[k]);
                sum += arr2[k];
            }
            printf("Child %d (%d): sum = %d\n", i, getpid(), sum);
            close(fd2[0]);
            write(fd2[1], &sum, sizeof(int));
            close(fd2[1]);
            exit(0);
        }
    }
    return 0;
}

static void dump_vector(const char *tag, size_t size, const int *data)
{
    int length = printf("%s (%zu):", tag, size);
    for (size_t i = 0; i < size; i++)
    {
        length += printf(" %2d", data[i]);
        if (length > 60)
        {
            length = 0;
            putchar('\n');
        }
    }
    if (length > 0)
        putchar('\n');
}

I find that functions like dump_vector() are very helpful; I write them for many data structures. Sometimes I accept a FILE *fp argument too, but the tag is crucial. For arrays, size and data are necessary; for single structures, just the structure, of course.

Example output

Dwse mou tis grammes tou pinaka
4
Dwse mou tis steiles tou pinaka
10
12  12  4   3   8   12  6   4   2   10  
10  13  14  13  13  1   7   12  4   8   
7   12  19  12  14  18  20  13  8   8   
5   14  7   11  19  16  4   12  14  18  
arr2 - parent (10): 12 12  4  3  8 12  6  4  2 10
arr2 - child (10): 12 12  4  3  8 12  6  4  2 10
Child 0 (15771): sum = 73
the sum of the row is: 73
arr2 - parent (10): 10 13 14 13 13  1  7 12  4  8
arr2 - child (10): 10 13 14 13 13  1  7 12  4  8
Child 1 (15772): sum = 95
the sum of the row is: 95
arr2 - parent (10):  7 12 19 12 14 18 20 13  8  8
arr2 - child (10):  7 12 19 12 14 18 20 13  8  8
Child 2 (15773): sum = 131
the sum of the row is: 131
arr2 - parent (10):  5 14  7 11 19 16  4 12 14 18
arr2 - child (10):  5 14  7 11 19 16  4 12 14 18
Child 3 (15774): sum = 120
the sum of the row is: 120
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278