3

In the code below a process creates one child (fork()) and then the child replaces itself by calling exec(). The stdout of the exec is written in a pipe instead of the shell. Then the parent process reads from the pipe what the exec has written with while (read(pipefd[0], buffer, sizeof(buffer)) != 0)

Can someone tell me how to do the exact same thing as described above but with N number of children processes (who replace themselves with exec as above).

int pipefd[2];
pipe(pipefd);

if (fork() == 0)
{
    close(pipefd[0]);    // close reading end in the child

    dup2(pipefd[1], 1);  // send stdout to the pipe
    dup2(pipefd[1], 2);  // send stderr to the pipe

    close(pipefd[1]);    // this descriptor is no longer needed

    exec(...);
}
else
{
    // parent

    char buffer[1024];

    close(pipefd[1]);  // close the write end of the pipe in the parent

    while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
    {
    }
}
3
  • 1
    I don't have the time to type out a full answer, but select() is the function you are looking for -- it will wait on N file handles simultaneously and give you a list of "ready" file handles ("ready" meaning "will not block on read or has been closed on the other end"). Commented Sep 28, 2012 at 18:16
  • Do the children need to be writing concurrently? Commented Sep 28, 2012 at 18:16
  • Yes they need to write concurrently Commented Sep 28, 2012 at 18:35

3 Answers 3

1

I found the answer. I made an array of pipes so that a process does not overwrite the output of another process.

Here is my code. Do you find any mistake?

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

#define N 10

int main(int argc, char *argv[]) {
    ssize_t readlen;
    int pipefd[N][2];
    int i;
    for (i = 0; i < N; i++) {
        pipe(pipefd[i]);
    }

    int pid = getpid();

    for (i = 0; i < N; i++) {
        if (fork() == 0) //The parent process will keep looping
        {

            close(pipefd[i][0]);    // close reading end in the child

            dup2(pipefd[i][1], 1);  // send stdout to the pipe
            dup2(pipefd[i][1], 2);  // send stderr to the pipe

            close(pipefd[i][1]);    // this descriptor is no longer needed

            char b[50];
            sprintf( b, "%d", i);

            execl("/bin/echo", "echo", b,NULL);


        }
    }

    if (pid == getpid()) {

        // parent

        char buffer[1024];

        for (i = 0; i < N; i++) {
            close(pipefd[i][1]);  // close the write end of the pipe in the parent

            while ((readlen=read(pipefd[i][0], buffer, sizeof(buffer))) != 0)
            {
                        buffer[readlen] = '\0';
            }

            printf("%s\n",buffer);

        }
    }


}
Sign up to request clarification or add additional context in comments.

2 Comments

The task is so easy, but code is too hard. Wish you find a more simple implementation.
you can exit(0); in the fork() == 0 instead of checking the if PID matches later on
0

Maybe this code would do the job:

const int N = 10; //Number of child processes
int pipefd[2];
pipe(pipefd);
int i;
for (i = 0; i < N; i++) {
    if (fork() == 0) //The parent process will keep looping
    {
        close(pipefd[0]);    // close reading end in the child

        dup2(pipefd[1], 1);  // send stdout to the pipe
        dup2(pipefd[1], 2);  // send stderr to the pipe

        close(pipefd[1]);    // this descriptor is no longer needed

        exec(...);
    }
}

// parent

char buffer[1024];

close(pipefd[1]);  // close the write end of the pipe in the parent

while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
{
}

WARNING: the output will be mixed. If you want all processes to dump data without being mixed, then you should manage to synchronize processes (by means of public locks, for example).

4 Comments

I think you can create named chanel in any place of the file system (like a local socket) and read all received data to parent process. So child processes must write them getted data to this channel. It will be unix-like architecture.
Well, I think it's unnecessary if we have the pipe mechanism. Your solution would not resolve the problem of mixing data because the write operations to the local socket may be scattered in several transactions by the OS. Am I wrong?
You can pass id of the child process who sends data. And source code will be more simple.
I tried this and it does not work. It only prints some of the processes' output. I used echo "test" in the execl() and I printed the buffer with printf("%s\n",buffer). I never got 10 "test" as a result, only 2 or 3.
0

I think you can create named chanel in any place of the file system (like a local socket) and read all received data to parent process. So child processes must write their getted data to this channel. It will be unix-like architecture.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.