I'm trying to do a simple fork -> execute another program -> say "hello" to that child process -> read back something -> print what received.
The program used as child just waits for any line of input and prints something to the stdout like "hello there!"
This is my "host" program (that is not working):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#define IN 0
#define OUT 1
#define CHILD 0
main ()
{
pid_t pid;
int pipefd[2];
FILE* output;
char buf[256];
pipe(pipefd);
pid = fork();
if (pid == CHILD)
{
printf("child\n");
dup2(pipefd[IN], IN);
dup2(pipefd[OUT], OUT);
execl("./test", "test", (char*) NULL);
}
else
{
sleep(1);
printf("parent\n");
write(pipefd[IN], "hello!", 10); // write message to the process
read(pipefd[OUT], buf, sizeof(buf));
printf("received: %s\n", buf);
}
}
I get this:
child
[.. waits 1 second ..]
parent
received:
What am I missing? Thanks!
EDIT (test.c):
By request, this is the child program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int getln(char line[])
{
int nch = 0;
int c;
while((c = getchar()) != EOF)
{
if(c == '\n') break;
line[nch] = c;
nch++;
}
if(c == EOF && nch == 0) return EOF;
return nch;
}
main()
{
char line[20];
getln(line);
printf("hello there!", line);
fflush(stdout);
return 0;
}
It doesn't work because you're not using dup2() for its intended purpose. dup2() is for duplicating file descriptors, not for piping data from one stream to another. Look up the pipe() function if you want to redirect the output from one program to the input of another (but not the reverse).
After dup2(f1, 0) , whatever file was opened on descriptor f1 is now also opened (with the same mode and position) on descriptor 0, i.e. on standard input. No locking is involved.
To capture both stdout and stderr you can either create two separate pipes, or if it is acceptable for the streams to be mixed, copy the same file descriptor onto both STDOUT_FILENO and STDERR_FILENO by calling dup2 twice.
pipe() is used for passing information from one process to another. pipe() is unidirectional therefore, for two-way communication between processes, two pipes can be set up, one for each direction.
You're always suppose to read from file-descriptor 0
, and write to file-descriptor 1
with pipes ... you have this relationship reversed in the parent process. For what you're wanting to-do, you may end up needing two pipes for two-way communication between the parent and child that avoids situations where the parent ends up reading the contents it wrote to the pipe since process scheduling is non-deterministic (i.e., the child is not guaranteed to read what the parent wrote to the pipe if the parent is also reading from the same pipe since the parent could just end up writing and then reading with no interleaving of the child process to read what the parent wrote).
Change your code to the following:
main ()
{
pid_t pid;
int pipe_to_child[2];
int pipe_from_child[2];
FILE* output;
char buf[256];
pipe(pipe_to_child);
pipe(pipe_from_child);
pid = fork();
if (pid == CHILD)
{
printf("child\n");
//child process not using these ends of the pipe, so close them
close(pipe_to_child[1]);
close(pipe_from_child[0]);
dup2(pipe_to_child[0], fileno(stdin));
dup2(pipe_from_child[1], fileno(stdout));
execl("./test", "test", (char*) NULL);
}
else
{
sleep(1);
printf("parent\n");
write(pipe_to_child[1], "hello!\n", 10); // write message to the process
read(pipe_from_child[0], buf, sizeof(buf));
printf("received: %s\n", buf);
}
}
You need two pipes for this: one for the child process's stdin, and one for its stdout. You cannot reuse the two ends of a pipe as two pipes.
Also, this line of the parent program
write(pipefd[IN], "hello!", 10); // write message to the process
does not write a newline, so getln
in the child will never return. (Furthermore, "hello!" has only six characters, but you are writing ten.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With