Reputation: 97
I am learning to use Linux system calls using C. I don't understand the use of dup2
at all. So far I did dup2
for 2 commands and it works okay, but I can't think of a way for doing 3+ commands.
For example if I want to execute three commands:
./program1
./program2
./program3
Suppose these three program depends on user input. How can I use fork()
and dup2()
to pipe the outputs of these program?
For only 2 commands I have done this and it works like a charm:
pid2=fork();
if(pid2==0)
{
close(pipe1[0]);
dup2(pipe1[1], STDOUT_FILENO);
close(pipe1[1]);
execvp("./addone",argp);
}
else
{
wait(NULL);
close(pipe1[1]);
dup2(pipe1[0], STDIN_FILENO);
close(pipe1[0]);
execvp("./addone",argp);
}
Upvotes: 0
Views: 1548
Reputation: 4286
First of, your else
is redundant as "the exec()
family of functions replaces the current process image with a new process image [exec(3) — Linux manual page]. So, the child will never continue execution past the if
block and the code in the else
block is the code that the parent should execute anyway.
For 3 processes to emulate the following bash behaviour ./addone | ./addone | ./addone
, you would want to write something like:
#include <unistd.h> // dup2(), pipe(), fork(), execvp()
#include <sys/wait.h> // waitpid()
int main() {
int pipe1[2], pipe2[2];
int pid0, pid1, pid2;
char *argp = {"./addone", "first_argument", "second_argument", NULL};
pipe(pipe1);
pid0 = fork();
if (pid0 == 0) {
// close the read end of pipe1:
close(pipe1[0]);
// redirect stdout to the write end of pipe1:
dup2(pipe1[1], 1);
execvp("./addone", argp);
}
pipe(pipe2);
pid1 = fork();
if (pid1 == 0) {
// close the write end of pipe1:
close(pipe1[1]);
// close the read end of pipe2:
close(pipe2[0]);
// redirect stdin to the read end of pipe1:
dup2(pipe1[0], 0);
// redirect stdout to the write end of pipe2:
dup2(pipe2[1], 1);
execvp("./addone", argp);
}
pid2 = fork();
if (pid2 == 0) {
// close unused pipe1:
close(pipe1[0]);
close(pipe1[1]);
// close the write end of pipe2:
close(pipe2[1]);
// redirect stdin to the read end of pipe2:
dup2(pipe2[0], 0);
execvp("./addone", argp);
}
waitpid(pid0, NULL, 0);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
}
Upvotes: 1