Write something in a process and read it in another - c

I want to write something in process A and read it in process B which is forked by A. But I find that B cannot read the content unless A is terminated. How can I write in process A while read in B without A quitting? My code is as follows.
#include <stdio.h>
#include <unistd.h>
int mypipe[2];
int main(){
FILE* f;
pid_t pid = 0;
int num = 0, temp;
pipe(mypipe);
pid = fork();
if (pid == (pid_t)0){
f = fdopen(mypipe[0], "r");
while (1){
fscanf(f, "%d", &temp);
printf("from child: %d\n", temp);
}
fclose(f);
}
else{
f = fdopen(mypipe[1], "w");
while (1){
scanf("%d", &num);
fprintf(f, "%d\n", num);
//break;
}
fclose(f);
}
return 0;
}

B cannot read the content unless A is terminated
This is because A doesn't actually write something. stdio streams (represented by FILE *) are buffered. You can set the buffering mode using setvbuf(). The stream you open on your pipe with fdopen() will be fully buffered by default, so no actual writes to the pipe occur until the buffer is full.
The easiest solution is to put a call to fflush() in your code anywhere you want writes to occur, e.g. in your code directly after the fprintf():
while (1){
scanf("%d", &num);
fprintf(f, "%d\n", num);
fflush(f);
//break;
}

First of all there are many unnecessary lines in your code. Instead of doing fdopen() you can directly use read() and write() system calls. Secondly fork() system call return 0 to the child and pid of the child process to the parent. Finally parent should wait for child to finish and clear it from memory to stop it becoming zombie.
This is the corrected version of your code works perfectly without break.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int status; // To get return status of file
// No need of FILE pointer
int mypipe[2]; // No need to make it global
pid_t pid = 0;
int num = 0, temp;
pipe(mypipe); // Create pipe
if((pid = fork()) == 0) // Child block
{
close(mypipe[1]); // Child will close the writing end
while (1)
{
read(mypipe[0],&temp,sizeof(int));
printf("from child: %d\n",temp);
}
exit(0); // Exit the child
}
else // Parent block
{
close(mypipe[0]); // Parent will close the reading end of pipe
while (1)
{
scanf("%d", &num);
write(mypipe[1],&num,sizeof(int));
}
}
// Parent should wait for child
wait(&status);
return 0;
}
Read the system calls man pages
man 2 read, man 2 write etc.

Related

Why SIGPIPE doesn't occur when the read end of a pipe is closed?

I'm trying to write a program with two processes:
One process generates some a + b problems and print it to its stdout (like printf("%d %d\n", a, b)), and gets the answer from another process through stdin, and log the answer to log.txt. When all the problems are asked, the process will print out "-1 -1" to indicate the end of the problems.
Another process receives the a + b problems through stdin (like scanf("%d%d", &a, &b)), and prints the answer to its stdout. When a = b = -1 the process exits.
I'm using two pairs of pipe to connect the two processes. I use dup2 to bind the pipes with stdin and stdout. My source code is shown below:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
// Get a + b question through stdin, and print answer to stdout
void calc_a_plus_b() {
int a, b;
while (scanf("%d%d", &a, &b) > 0)
{
if (a == -1 && b == -1)
break;
printf("%d\n", a + b);
fflush(stdout);
}
}
// Ask a + b through stdout, and get answer through stdin
// Log answer to log.txt
void ask_a_plus_b() {
FILE* log = fopen("log.txt", "w");
int i, a, b, c;
for (i = 0; i < 3; i++) {
a = i; b = i + 1;
printf("%d %d\n", a, b);
fflush(stdout);
scanf("%d", &c);
fprintf(log, "%d\n", c);
}
printf("-1 -1\n");
fclose(log);
}
int main()
{
pid_t ask_pid, calc_pid, term_pid;
int ask_to_calc[2], calc_to_ask[2]; // Two pairs of pipe
int status;
// Create pipe
pipe(ask_to_calc); pipe(calc_to_ask);
// Create calculate process
calc_pid = fork();
if (calc_pid == 0) {
// Close useless pipe
close(ask_to_calc[1]);
close(calc_to_ask[0]);
// Bind pipe to stdin and stdout
dup2(ask_to_calc[0], 0);
dup2(calc_to_ask[1], 1);
close(ask_to_calc[0]);
close(calc_to_ask[1]);
calc_a_plus_b();
return 0;
}
// Create ask process
ask_pid = fork();
if (ask_pid == 0) {
// Close useless pipe
close(ask_to_calc[0]);
close(calc_to_ask[1]);
// Bind pipe to stdin and stdout
dup2(calc_to_ask[0], 0);
dup2(ask_to_calc[1], 1);
ask_a_plus_b();
return 0;
}
// Wait for children to exit
while ((term_pid = wait(&status)) > 0) {
if (WIFSTOPPED(status))
{
// If child stopped but hasn't exited, ignore
continue;
} else if (WIFSIGNALED(status)) {
// Child exited due to signal
printf("%s terminated due to signal %d\n", ask_pid == term_pid ? "ask" : "calc", WTERMSIG(status));
} else {
// Child exited normally
printf("%s terminated normally\n", ask_pid == term_pid ? "ask" : "calc");
}
}
return 0;
}
This code runs normally, and prints out
calc terminated normally
ask terminated normally
From man 7 pipe (http://man7.org/linux/man-pages/man7/pipe.7.html) I know that, when all the file descriptors to the read end of a pipe is closed, and another process still tries to write to this pipe, a SIGPIPE will occur. So I decided to remove all the code in calc_a_plus_b and see what will happen.
Surprisingly, SIGPIPE doesn't occur. The program only prints out
calc terminated normally
after that the program is stuck. I guess this is because the printf in ask_a_plus_b is blocked.
I think I've closed all the file descriptors to the read end of the pipe ask_to_calc (I've bound the pipe to the stdin of the calculating process, but the process has exited so its stdin is also closed right?), so why SIGPIPE doesn't occur when the asking process tries to write to the pipe?
Thanks #Art for the comment. I forgot to close the pipes in the parent process-_-"
After closing the pipes in the parent process, the asking process is now terminated due to SIGPIPE.

Creating seperate child function for counting each letter in a file

I am trying to create separate child process for each letter that needs to be counted in a file. I have the file being read in a parent process, but the output is all zeros. I don't understand what I am doing wrong. I need to use child processes for each of the letters, but I am not exactly sure how to create separate processes for each letter. Please help! Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/wait.h>
int main(int argc, char **argv){
char characters[26] = { "abcdefghijklmnopqrstuvwxyz" };
int counter[26] = { 0 };
int n = 26;
int c;
char ch;
if (argc < 2)
return 1;
pid_t pids[26];
for (int i = 0; i < n; i++){
pids[i] = fork();
if (pids[i] < 0) {
printf("Error");
exit(1);
} else if (pids[i] == 0) {
while (c = fgetc(file) != EOF){
if (c == characters[i])
counter[i]++;
}
exit(0);
} else {
FILE *file = fopen(argv[1], "r");
if(file == NULL)
printf("File not found\n");
while (c = fgetc(file) != EOF);
fclose(file);
wait(NULL);
}
}
for (int i = 0; i < n; ++i){
printf("%c: %i\n", characters[i], counter[i]);
}
return 0;
}
The problem with forking when the parent has open a file for reading, is that
although all children inherit copies of open file descriptors, they all
share the same file description.
man fork
The child process is an exact duplicate of the parent process except for the following points:
[...]
The child inherits copies of the parent's set of open file descriptors. Each file descriptor in the child refers to the same open
file description (see open(2)) as the corresponding file descriptor in the parent. This means that the two file descriptors share
open file status flags, file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)).
You can do such a program, but you would have to synchronize the children with
each other, because every time a child does fgetc(file), the file description
advances for all children. The synchronization would have to be written such as
all children wait for the others to stop reading, do a rewind and then finally
read. In that case having all these children is no gain at all.
For more information about that, see this excellent answer from this
question: Can anyone explain a simple description regarding 'file descriptor' after fork()?
Another problem with your code is this:
printf("%c: %i\n", characters[i], counter[i]);
fork duplicates the process and they both run in separate memory spaces.
The children's counter is a copy of the parent's counter, but a modification
of counter in a child process will only affect the counter for that process,
the parent's counter is not affected by that. So in this case you are always
printing 0, because the parent never changed counter.
Also, even if the modification of a child's counter would somehow propagate to
the parent, the parent should wait for the child process to make the
modification before accessing the variable. Again synchronization would be
needed for that.
For the parent to benefit of the work of the children, it must communicate with
the children. One way to do it is by creating a pipe for each of the children. The
parent closes the writing end of the pipes, the children close the reading end
of the pipe. When the child does its work, it writes the results on the writing end of it's
pipe back to the parent and exits. The parent must then wait for every children,
read from the reading end of the pipe.
This program does exactly that:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
char characters[26] = "abcdefghijklmnopqrstuvwxyz";
if(argc != 2)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
return 1;
}
size_t i;
int pipes[26][2];
// creating the pipes for all children
for(i = 0; i < 26; ++i)
{
if(pipe(pipes[i]) < 0)
{
perror("unable to create a pipe");
return 1;
}
}
pid_t pids[26];
memset(pids, -1, sizeof pids);
for(i = 0; i < 26; ++i)
{
pids[i] = fork();
if(pids[i] < 0)
{
fprintf(stderr, "Unable to fork for child %lu: %s\n", i, strerror(errno));
continue;
}
if(pids[i] == 0)
{
// CHILD process
// closing reading end of pipe
close(pipes[i][0]);
FILE *fp = fopen(argv[1], "r");
if(fp == NULL)
{
close(pipes[i][1]);
exit(1);
}
int n = 0, c;
while((c = getc(fp)) != EOF)
{
if(c == characters[i])
n++;
}
// sending answer back to parent through the pipe
write(pipes[i][1], &n, sizeof n);
fclose(fp);
close(pipes[i][1]);
exit(0);
}
// PARENT process
// closing writing end of pipe
close(pipes[i][1]);
}
printf("Frequency of characters for %s\n", argv[1]);
for(i = 0; i < 26; ++i)
{
if(pids[i] < 0)
{
fprintf(stderr, "%c: could not create child worker\n", (char) i + 'a');
close(pipes[i][0]);
continue;
}
int status;
waitpid(pids[i], &status, 0);
if(WIFEXITED(status) && WEXITSTATUS(status) == 0)
{
// child ended normally and wrote result
int cnt;
read(pipes[i][0], &cnt, sizeof cnt);
printf("%c: %d\n", (char) i + 'a', cnt);
} else {
printf("%c: no answer from child\n", (char) i + 'a');
}
close(pipes[i][0]);
}
return 0;
}
The parent creates 26 pipes, each one for a child. The it creates an array for
the pids and initializes them to -1 (later for error checking). Then enters in
the loop and creates a new child and closes the writing end of the parent's pipe
for the i-th child. Then it goes again into a loop and checks if a child
process was created for every character. If that's the case, it waits for that
child to exit and checks it's exit status. If and only if the child exits
normally (with an exit status of 0), it reads from the reading end of the pipe
and prints the result, otherwise it prints an error message. Then it closes the
reading end of the pipe and exits.
Meanwhile every child closes its reading end of the pipe and open a file for
reading. By doing this, the children don't share the file description and can
independently from each other read the contents of the file and calculate the
frequency of the letter assigned to the child. If something goes wrong when
opening the file, the child closes the writing end of the pipe and exits with a
return status of 1, signalling to the parent, that something went wrong and that
it won't send any result through the pipe. If everything goes well, the child
writes the result in the writing end of the pipe and exits with an exit status
of 0.
The output of this program with the its source is:
$ ./counter counter.c
Frequency of characters for counter.c
a: 44
b: 5
c: 56
d: 39
e: 90
f: 40
g: 17
h: 26
i: 113
j: 1
k: 5
l: 35
m: 6
n: 68
o: 45
p: 59
q: 2
r: 78
s: 71
t: 65
u: 25
v: 5
w: 10
x: 3
y: 6
z: 5

How can I tell a child process the pid of another child process in C?

I am writing a program in which I need to create two child processes, a producer and a consumer. The producer writes on a file what is read from stdin, the consumer reads the same file after the producer has written the line. I need to synchronize the two processes and I wanted to do so by using signals, but I have now a problem in that I cannot send (using the kill() function) the signals from the consumer to the producer.
This is my program:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void catcherp(){};
void catcherc(){};
pid_t producer, consumer;
int main () {
int status_consumer, status_producer;
char string[128], reading[128];
FILE * fout, *finn;
producer = fork();
if (producer == 0){
signal(SIGUSR2, catcherp);
// producer process, child
while(1){
fout = fopen ("test.txt", "w");
printf ("?: ");
scanf ("%s", string);
fputs(string, fout);
fclose(fout);
kill(consumer, SIGUSR1);
pause();
}
exit(0);
} else {
// parent process
consumer = fork ();
if (consumer == 0) {
signal(SIGUSR1, catcherc);
// consumer process, child
while(1) {
pause();
finn = fopen ("test.txt", "r");
fgets(reading, 128, finn);
printf("%s\n", reading);
fclose(finn);
kill (producer, SIGUSR2);
}
exit(0);
} else {
printf("This is the parent process\n");
waitpid(producer, &status_producer, 0);
waitpid(consumer, &status_consumer, 0);
printf("The children exited\n");
}
}
return 0;
}
The exit(0) commands in both child processes are there because I still have to implement the exit condition for the loop. I am pretty sure that my problem lies in how I create the consumer process after creating the producer process. That means that the producer sees the "consumer" pid to be 0, which terminates the program.
Now, I would like to understand how I'm supposed to create two concurrent processes using the fork() function (if it's possible), can someone enlighten me?
In the end I managed to solve the problem, but I had to use the temporary file in order to get the pid of the producer process when inside the consumer process.
I was hoping to find a smarter way but the solution given by the course was basically the same.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
void catcher(){};
int main () {
int status_consumer, status_producer; // needed for the waitpid functions
pid_t producer, consumer; // pids of the child processes
char string[128]; // input string
FILE * f; // fp
signal (SIGUSR1, catcher);
consumer = fork();
if (consumer == 0) {
// child process
while (1) {
pause(); // wait for the ready signal from the sender
f = fopen ("tmp.txt", "r");
fscanf (f, "%d %s", &producer, string); // read string and the pid of the sender
printf("%s\n", string);
fclose(f);
if (strcmp("end", string) == 0) {
break; // exit the loop when the word "end" is read
}
kill (producer, SIGUSR1);
}
exit(0);
} else {
producer = fork ();
if (producer == 0) {
// child process
while(1) {
f = fopen ("tmp.txt", "w");
printf("?: ");
scanf("%s", string); // read from stdin the string
fprintf(f, "%d\t%s\n", getpid(), string); // write on tmp.txt the string
fclose(f);
kill(consumer, SIGUSR1);
if (strcmp("end", string) == 0){
break; // exit the loop when the word "end" is read
}
pause();
}
} else {
// parent process
waitpid(producer, &status_producer, 0);
waitpid(consumer, &status_consumer, 0);
}
}
return 0; // end of program
}
Thanks for the comments

Using a pipe to read array of strings with C

I am learning about using pipes with C right now, and I am having some difficulty writing a list of strings, one-by-one, to the pipe in the child process, and then read them from the pipe in the parent process. Here is my current code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
int main()
{
int pfd[2];
char buf[1000];
int cfork;
if (pipe(pfd) == -1) {
exit(1);
}
cfork = fork();
if (cfork == -1) {
printf("Fork Failed\n");
exit(1);
}
else if (cfork == 0) {
printf("Child Process\n");
char *fruit[] = {
"Orange", "Apple",
"Banana", "Pear"
};
int num_fruit = 4;
for (int i = 0; i < num_fruit; i++) {
printf("Current fruit: %s\n", fruit[i]);
write(pfd[1], fruit[i], (strlen(fruit[i])));
}
_exit(0);
}
else {
printf("Parent Process\n");
read(pfd[0], buf, sizeof(buf));
printf("Fruit Fetched: %s\n", buf);
wait(NULL);
}
return 0;
}
What I am trying to do, is in the child, read a fruit string, write it to the pipe, and have the parent read this string and print it, until all the strings have been printed. My trouble is that the child, since it's in a loop, just keeps adding each string to the buffer, so the program, as it stands, prints out "OrangeAppleBanana". I am pretty sure I will need a loop in the parent as well, but when I've tried a while loop that waits for some end condition string sent by the child (for example "done"), my program still gets stuck in an infinite loop.
What is the most straightforward way, for someone new to C, to write strings in the child one -by-one, and have the parent process print them out one-by-one?
EDIT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
int main()
{
int pfd[2];
int cfork;
if (pipe(pfd) == -1) {
exit(1);
}
cfork = fork();
if (cfork == -1) {
printf("Fork Failed\n");
exit(1);
}
else if (cfork == 0) {
int numbers[] = {
1, 2,
3, 4
};
int limit = 4;
close(pfd[0]);
for (int i = 0; i < limit; i++) {
printf("Child - Current Number: %d\n", numbers[i]);
write(pfd[1], &numbers[i], sizeof(numbers[i]));
}
close(pfd[1]);
_exit(0);
}
else {
int temp;
int reads = 4;
close(pfd[1]);
for (int i = 0; i < reads; i++) {
read(pfd[0], &temp, sizeof(temp));
printf("Parent - Number Fetched: %d\n", temp);
}
close(pfd[0]);
waitpid(-1, NULL, 0);
}
return 0;
This is my new code, where I use integers instead of strings. Seems to work so far. Still not sure what I was doing wrong with strings though.
I believe your problem is with "strings". Strings in C are null terminated, so when you are sending them via pipe, receiver(parent) doesn't know where a string ends. Strlen does count the number of characters in a string, but not the null charatter. You should do:
write(pfd[1], fruit[i], (strlen(fruit[i]))+1);
Parent can now know when and where to split your string.
The other problem is that you need to loop in the parrent as well. You need to set up a condition in the loop, which checks for EOF. In your example, where you know you are going to receive 4 fruits, you can just loop 4 times.
It's a good practice to close read and write end of pipes you don't need. In your example, child should close the reading end, while parent should close the writing end. You can do this with:
close(pfd[0]); //use this in child
close(pfd[1]); //use this in parent
You should also get used to closing all descriptors you don't need. In your example, you should close the pipe in both child and parent process after you are finished with writing / reading. This way, you could create a read loop condition, which closes after EOF. (When child closes pipe, receiver can end)
As an extra tip, try error reporting with "perror"
http://www.tutorialspoint.com/c_standard_library/c_function_perror.htm
//Child
close(pfd[0]); // Close read end this blocks if parent is reading from pipe
write(pfd[1]...); // write data into pipe
close(pfd[1]); // close write end of pipe now the pipe is ready to read
// Parent
close(pfd[1]); // close write end of pipe blocks if child is writing to pipe.
read(pfd[0] ...);
close(pfd[0]..); // close read end so pipe is ready to write to.

New to IPC, can't get my pipe to work

Sorry for the length of this post... I've encountered about a zillion problems in this. Up front I'll say I'm a student and my professor is a worthless resource. So, all I want to to do is have producer fork, then the parent producer will count some stuff in a file and send two ints to consumer, which was launched by the child process. I've tested everything, the fork and the file stuff works and I have printf statements all over the place so I know what is being done and where the code is at.
When I added the
if (pipe(pipefd) == -1) {
perror("pipe");
}
it caused my parent to just terminate. It reaches "parent pipe open" but then it dies. I checked with $ ps to see if it was just hung, but it's not there; it just dies. If I take that snippet out, it runs to the end but I presume if that code isn't there, then it's not actually aware that pipefd is a pipe... right?
I did search on this site and found another example of this and followed what he did as well as the answer and mine just refuses to work. I'm pretty sure it's a trivially easy thing to fix but I've run out of ideas of what to try :(
I don't really want to post all my code because it'll be a huge wall of text but I don't want to accidentally cut something out that turns out to be important either.
producer.c
#include <stdio.h> /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* _exit, fork, execl */
#include <stdlib.h> /* exit */
#include <errno.h> /* errno */
#include <string.h> /* strlen */
#include <sys/wait.h> /* wait */
#define SLEEP_TIME 8
int main (int argc, char *argv[]){
//PID
pid_t local_pid;
local_pid = fork();
//Logic to determine if the process running is the parent or the child
if (local_pid == -1) {
/* Error:
* When fork() returns -1, an error happened
* (for example, number of processes reached the limit).
*/
fprintf(stderr, "can't fork, error %d\n", errno);
exit(EXIT_FAILURE);
} else if (local_pid == 0) {
//Child specific code
int child;
char *temp[] = {NULL};
printf("Child PID found\n");
child = execv("./consumer", temp);
_exit(0);
} else {
//Parent specific code
printf("Parent running\n");
//open file
FILE * randStrings;
randStrings = fopen("randStrings.txt", "r");
int file_length;
int num_of_e = 0;
int c; //using this as a char
//until eof
while (feof(randStrings) == 0) {
c = fgetc(randStrings);
//calculate length of file
file_length++;
//count e chars
if (c == 'e') {
num_of_e++;
}
}
//close file
fclose(randStrings);
//send bundle to child
int a[2];
a[0] = num_of_e;
a[1] = file_length;
printf("num of e = %i\n", a[0]);
printf("len = %i\n", a[1]);
//set up parent pipe
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
printf("x\n");
}
printf("parent pipe open\n");
close(pipefd[0]); //close the read end
write(pipefd[1], &a[0], sizeof(int));
write(pipefd[1], &a[1], sizeof(int));
close(pipefd[1]);
printf("parent pipe closed\n");
//wait for child to finish running
wait(NULL);
printf("parent out\n");
//terminate
}
}
and consumer.c
#include <stdio.h> /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* _exit, fork, execl */
#include <stdlib.h> /* exit */
#include <errno.h> /* errno */
#define SLEEP_TIME 5
int main (int argc, char *argv[]){
sleep(SLEEP_TIME);
printf("Child program launched\n");
//receive bundle
int pipefd[2];
int buf[2];
if (pipe(pipefd) == -1) {
perror("pipe");
printf("child x\n");
}
close(pipefd[1]); //child closes write end
buf[0] = 0;
buf[1] = 0;
/*int i = 0; // i dont like this
while (read(pipefd[0], &buf[i], sizeof(int)) > 0) {
i++;
}*/
printf("child reading pipe\n");
read(pipefd[0], &buf[0], sizeof(int));
read(pipefd[0], &buf[1], sizeof(int));
close(pipefd[0]);
//buf should have the stuff in it
int num_of_e = buf[0];
int file_length = buf[1];
printf("child num of e = %i\n", num_of_e);
printf("child len = %i\n", file_length);
//open file
FILE * resultStrings;
resultStrings = fopen("resultStrings.txt", "w");
for (int i = 0; i < num_of_e; i++) {
//write num_of_e e chars
fputc('e', resultStrings);
}
//or if no e chars, write - chars
if (num_of_e == 0) {
for (int i = 0; i < file_length; i++) {
//write file_length '-' chars
fputc('-', resultStrings);
}
}
//close file
fclose(resultStrings);
printf("child out\n");
}
if you're still here after all that, you deserve a thank you just due to the length of this.
You're doing it wrong. The whole mechanism works because a child process inherits the parent's open file descriptors.
It should go like this:
Open the pipe with pipe(pipefd)
fork()
Parent (producer):
closes the read side (pipefd[0])
writes to the write side (pipefd[1])
Child (consumer):
closes the write side (pipefd[1])
reads from the read side (pipefd[0]) or calls exec
You are opening distinct pipes in both the parent and child process (after you've forked.) It needs to happen before you fork.
Now since you're execing, the new process needs to be aware of read-only pipe. There are a couple ways you could do this:
Pass it the file descriptor number (pipefd[0]) on the command line
dup2(1, fd) it to be the stdin of the newly exec'd process

Resources