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 looks like you have your pipe descriptors mixed up. After calling
pipe()
,pipefd[0]
is the read end of the pipe, andpipefd[1]
is the write end of the pipe. You're writing to the read end, and reading from the write end.Also, you're trying to use one pipe for both stdin and stdout of the child process. I don't think this is really what you want to do (you will need two pipes).
You're always suppose to read from file-descriptor
0
, and write to file-descriptor1
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:
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
does not write a newline, so
getln
in the child will never return. (Furthermore, "hello!" has only six characters, but you are writing ten.)You probably should use
wait
orwaitpid
.Looks like you have your IN/OUT backwards for the pipe --
pipefd[0]
is the read end of the pipe, so writing to it (as the parent does) is nonsensical and will fail. Similarlypipefd[1]
is the write end so reading from it (as the parent does) will also fail. You should ALWAYS check the return values of the read and write calls, to see if you're getting any errorsOthers are saying that the pipe is mono-directional, which is what I thought at first. But actually that's not what my man page says:
However, this does mean that if the parent is writing to
pipefd[0]
, then the child should read frompipefd[1]
, so you are associating the wrong side of the pipe with the child's stdin and stdout.From the man page, it does seem like you can do this with one pipe. But it might be clearer code to use two.
It seems like you are thinking of each element of
pipefd
as a separate pipe, but that's not the case.