How to exit while loop when read() blocks - c

In a problem given by university we have to pipe from a parent process(P1) to its child P2, and afterwards P2 must pipe to another child of P1, the other child is P3. Both P2 and P3 are to be written in c and made into executable files. They will then by execed by child processes in P1.
P1 writes the numbers 1 to 10000 to stdout, P2 reads them through its stdin, removes the numbers divisible by 2, and writes the result to its stdout. P3 reads those numbers through its stdin, filters out the results that are divisible by 3, and writes everything to a file.
I have managed to implement absolutely everything, but my child processes do not end. The reason for this, I believe, is that I have used the following method to read the input in each child:
while(n=read(0, &i, sizeof(i))>0)
The problem here, as I understand it, is that read blocks when it doesn't get any bytes. As P1 writes the 10000 numbers using:
for(i=1; i<=10000; i++){
write(1, &i, sizeof(i));
}
Neither child process ever has any reason to believe that no more data is coming its way. Therefore, each read simply blocks waiting for a byte that will never come.
Can anyone suggest a way to overcome this roadblock?
The code of each process is as follows:
Parent:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
// pipe to send input string from parent
// Child prints to file
int fd1[2]; // Used to store two ends of first pipe
int fd2[2]; // Used to store two ends of second pipe
//variables
int n, i, status1, status2;
char *args1[]={"./Div2",NULL};
char *args2[]={"./Div3",NULL};
//child process ids
pid_t pid1, pid2;
//open pipe 1
if (pipe(fd1)==-1)
{
fprintf(stderr, "Pipe 1 Failed" );
return 1;
}
//open pipe 2
if (pipe(fd2)==-1)
{
fprintf(stderr, "Pipe 2 Failed" );
return 1;
}
//create child 1
pid1 = fork();
if(pid1<0){
printf("Error creating child1\n");
return(1);
}
if(pid1==0){ //child1
if(close(fd1[1])<0){ //child does not write to pipe 1
error();
}
if(close(fd2[0])<0){ //child does not read from pipe 2
error();
}
dup2(fd1[0], 0); //redirect stdin
dup2(fd2[1], 1); //redirect stdout
execvp(args1[0],args1);
if(close(fd1[0])<0){ //close used pipe
error();
}
if(close(fd2[0])<0){ //close used pipe
error();
}
exit(0);
}
pid2=fork();
if(pid2<0){
printf("Error creating child2\n");
return(1);
}
if(pid2==0){ //child2
if(close(fd1[0])<0){ //child does not use pipe 1
error();
}
if(close(fd1[1])<0){
error();
}
if(close(fd2[1])<0){ //child does not write to pipe 2
error();
}
dup2(fd2[0], 0); //redirect stdin
execvp(args2[0], args2);
if(close(fd2[0])<0){ //close pipe after use
error();
}
exit(0);
}
//parent
//parent doesn't read from the pipe
if(close(fd1[0])<0){
error();
}
if(close(fd2[0])<0){
error();
}
if(close(fd2[1])<0){
error();
}
dup2(fd1[1], 1); //redirect stdout
for(i=1; i<=10000; i++){
write(1, &i, sizeof(i));
}
if(close(fd1[1])<0){
error();
}
int returnedPID1=waitpid(pid1, &status1, 0);
if(returnedPID1==pid1){
printf("Parent waited for child as predicted\n");
}
int returnedPID2=waitpid(pid2, &status2, 0);
if(returnedPID2==pid2){
printf("Parent waited for child as predicted\n");
}
_exit(0);
}
P2 (includes excluded)
int main()
{
int n;
int i;
while((n=read(0, &i, 4))>0){
if((i%2)!=0){
write(1, &i, sizeof(i));
}
}
return;
}
P3
int main()
{
int n;
int i;
char tmp[12] = {0x0};
char *arg[]= {"/home/eric/Documents/pr3/test.txt"};
int fp = open(arg[0], O_WRONLY|O_CREAT|O_TRUNC, 0666);
if(fp<0){
printf("Error opening file\n");
_exit(1);
}
while((n=read(0, &i, 4))>0){
if((i%3)!=0){
sprintf(tmp,"%11d", i);
write(fp, tmp, strlen(tmp));
}
}
return;
}
Thanks guys.

Except in case of error, exec never returns. So when you write:
execvp(args1[0],args1);
if(close(fd1[0])<0){ //close used pipe
error();
}
you are wrong to expect the file descriptor to be closed. Close them before you exec. They are getting left open. Although in your particular case the problem is that the parent never closes fd 1. The parent has two file descriptors that are writing into the pipe ( fd[1] and 1), and you need to close them both before the child reading the pipe will finish.

Related

Creating pipes in C for inter process communication between multiple processes

There are already multiple answers to this question but none of them have been able to help me solve my problem. I am trying to understand IPC using an anonymous pipe in C.
From my understanding of pipes, they are a one way communication channel with one read end and one write end.
Assuming we have two c files one named parent.c and the other child.c. What I am trying to achieve is to be able to create 5 or more child processes. After this the parent and the child should communicate with the child processes through standard input and standard output, but since I want to be able to print what the parent receives from the child I'll instead tie the pipes to standard error output using dup2.
In summary
1. Run a parent program which spins up 5 or more child processes and runs them.
2. The child process waits for an input from the parent using scanf.
3. The parent sends a message to the child process.
4. The child process receives the message and sends a reply to the parent and exits.
5. The parent process prints the received message and prints it then exits.
parent.c
// Parentc
#include <stdio.h>
#include <stdlib.h>
#include <uinstd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, const char *argv[]){
// File descriptors for the pipes
int read_pipe[2]; // From child to parent
int write_pipe[2]; // From parent to child
pid_t process_id;
int exit_status;
// Try to fork 5 child processes
for(int i = 0; i < 5; i++){
if(pipe(write_pipe) == -1 || pipe(read_pipe) == -1){
perror("Pipe");
exit(1);
}
// Spin a child process
process_id = fork();
if(process_id == -1){
perror("Fork");
exit(1);
} else if(processId == 0) {
// The child process
// I don't know what to do here, The idea is to close the
// unneeded end of the pipes and wait for input from the parent
// process
// Start the ./child
execl("./child", "");
} else {
// The parent process
char recieved_data[1024];
// Send data to child since stderr is duplicated in the pipe
// It sends the pid of the child
fprintf(stderr, "Test data to %d ", process_id);
// Wait to recieve data from child
// Don't know how to do that
// Print the recieved data
printf("Parent recieved: \"%s\"\n", recieved_data);
wait(&exit_status); // Will wait till all children exit before exiting
}
}
return 0;
}
The child.c is a simple program as shown below
child.c
#include <stdio.h>
int main(int argc, const char *argv[]){
char data_buffer[1024];
// Wait for input from parent
scanf("%s", data_buffer);
// Send data back to parent
printf("Child process: %s", data_buffer);
return 0;
}
Expected output
$ ./parent
parent recived: "Child process: Test data to 12345"
parent recived: "Child process: Test data to 12346"
parent recived: "Child process: Test data to 12347"
parent recived: "Child process: Test data to 12348"
parent recived: "Child process: Test data to 12349"
Where 12345, 12346....12349 is the process id of the child process
Here you have a code i did, and i will use to explain to you:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main() {
char buff[1024];
int aux, i, count;
int fds[2], fdss[2];
pipe(fds); //Here we initialize the file descriptors
pipe(fdss);
mode_t fd_mode = S_IRWXU;
for (i = 0; i < 3; i++) {
aux = fork();
if (aux == 0)
break;
}
switch (i) {
case 0:
printf("Write something:\n");
scanf("%s[^\n]", buff);
i = 0;
count = 0;
while(buff[i] != '\0') {
count++;
i++;
}
dup2(fds[1], 1);
close(fds[1]);
close(fds[0]);
close(fdss[0]);
close(fdss[1]);
write (1, buff, sizeof(buff));
break;
case 1:
dup2(fds[0], 0);
dup2(fdss[1], 1);
close(fds[0]);
close(fds[1]);
close(fdss[0]);
close(fdss[1]);
//
if (execl("/bin/grep", "grep", "example", NULL) == -1) {
printf("Error\n");
exit (1);
}
break;
case 2:
aux = open("result.txt", O_RDWR | O_CREAT , S_IRWXU);
dup2(fdss[0], 0);
dup2(aux, 1);
close(fds[0]);
close(fds[1]);
close(fdss[0]);
close(fdss[1]);
close(aux);
if (execl("/usr/bin/wc", "wc", "-l", NULL) == -1) {
printf("Error \n");
exit (1);
}
}
close(fds[0]);
close(fds[1]);
close(fdss[0]);
close(fdss[1]);
for (i = 0; i < 3; i++) wait(NULL);
return 0;
}
Ok, let's start:
We create and initialize pipes with pipe()
Then we write our code and before execl() we change the file descriptors, in order to pass the text we will write in the console, through processes and finally write in a file called result.txt the result of the "grep example" command applied to the text we have written.
The function dup2(new_descriptor, old_descriptor) is copying the new descriptor into the old descriptor and closes the old descriptor. For example:
Before dup2(fds[1], 1) we have:
0 STDIN
1 STDOUT
2 STDERR
After dup2(fds[1], 1) we have:
0 STDIN
1 fds[1]
2 STDERR
NOTE: If you don't want to use 1, yo can simply write STDOUT_FILENO
So now we are able to write through processes and in my example to a file too

Can I use pipe as read at parent and write in child?

I'm now learning how to use pipes correctly. I found examples only for write in parent and read in child, but I want to know how can I do it reverse. I tried like this:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
int main(){
int p1[2], p2[2];
char original[]="This is a string\n ";
pid_t child2;
pid_t child=fork();
if (child>0)
{
child2 = fork();
if(child2>0){
wait();
printf("I'm the parrent.\n");
close(p1[1]);
close(p2[1]);
printf("Parrent read p1:\n");
if (read(p1[0], original, sizeof(original)) == -1)
perror("read() error in parent p1");
else printf("parent read '%s' from pipe 1\n", original);
printf("Parrent read p2:\n");
if (read(p2[0], original, sizeof(original)) == -1)
perror("read() error in parent p2");
else printf("parent read '%s' from pipe 2\n", original);
}
else{
printf("Child2 \n");
pipe(p2);
close(p2[0]);
if (write(p2[1], original, sizeof(original)+1) == -1)
perror("write() error in child2");
//close(p2[1]);
}
}
else
{
printf("Child1 \n");
pipe(p1);
close(p1[0]);
if (write(p1[1], original, sizeof(original)+1) == -1)
perror("write() error in child1");
//close(p1[1]);
}
return 0;
}
But this way give to me error at reading in parent. read() error in parent p1: Bad file descriptor both times, at p1 and also at p2. So, can I do this this way or not? Or this is just something trivial error?
As already said you just need to invert the indexes for closing the pipes and the read/write.
Your code was almost correct. Two things were wrong: on the parent you were first closing the pipes and then calling pipe(): it should be the other way round: first you create both of the pipes and then close the corresponding element, all in the parent.
Secondly you should call wait after setting the pipes otherwise it does not work. Guessing you want to wait for all the children you should call wait(NULL). I do not know what you meant with wait().
The complete code:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(){
int p1[2], p2[2];
char original[]="This is a string\n ";
pid_t child2;
pid_t child=fork();
if (child>0)
{
child2 = fork();
if(child2>0){
printf("I'm the parrent.\n");
pipe(p1); //ADDED
pipe(p2); //ADDED
close(p1[1]);
close(p2[1]);
wait(NULL); //DON'T GET IT WHY? if u want to wait all children,
//wait after setting the pipes.
printf("Parrent read p1:\n");
if (read(p1[0], original, sizeof(original)) == -1)
perror("read() error in parent p1");
else printf("parent read '%s' from pipe 1\n", original);
printf("Parrent read p2:\n");
if (read(p2[0], original, sizeof(original)) == -1)
perror("read() error in parent p2");
else printf("parent read '%s' from pipe 2\n", original);
}
else{
printf("Child2 \n");
//pipe(p2); ERROR HERE
close(p2[0]);
if (write(p2[1], original, sizeof(original)+1) == -1)
perror("write() error in child2");
//close(p2[1]);
}
}
}

C Programming: Segmentation Fault (Core Dumped)

The program i am trying to write is trying to demonstrate how IPC works on Linux, but i keep getting a core dump error. It compiles fine and will run up until the last output statement in the parent process.
My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <err.h>
#include <sysexits.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#define SHM_SIZE 15
int main (int argc, char ** argv[]) {
pid_t pid; //pid variable of type pid
int shmid; //shared memory id
int key = 1776; //randomly chosen key
char *shm; //shared memory name
int pipefd[2];
char buff;
pid = fork(); //creating child process
pipe(pipefd); //creating pipe
if (pid < 0) {
fprintf(stderr, "Fork Failed");
return -1;
} else if (pid == 0) {
shmid = shmget(key, SHM_SIZE, 0);
shm = shmat(shmid, 0, 0);
char *n = (char *) shm;
printf("hello i am the child process. my pid is %d. what is your name?: ", getpid());
scanf("%s", n);
printf("\n");
///////////////////////////////////////////////////////////////////////////////////////
close(pipefd[1]);
printf("pipe opened on child end");
printf("\n");
while(read(pipefd[0], &buff, 1) > 0) {
write(1, &buff, 1);
}
write(1, "\n", 1);
close(pipefd[0]);
printf("pipe successfully closed");
printf("\n");
exit(EXIT_SUCCESS);
} else {
shmid = shmget(key, SHM_SIZE, 0777 | IPC_CREAT);
shm = shmat(shmid, 0, 0);
wait(NULL);
printf("\nThis is Child's Parent. My pid is %d. Nice to me you %s.\n", getpid(), shm);
printf("\n");
//////////////////////////////////////////////////////////////////////////////////////
close(pipefd[0]);
printf("pipe open on parent end");
printf("\n");
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]);
printf("pipe successfully closed");
wait(NULL);
exit(EXIT_SUCCESS);
}
return 0;
}
Does it have something to do with my args[]? Such as could i be accessing memory out of reach? Or am trying to access some invalid pointer?
Many Thanks!
You have several problems in your code
Create the pipe before the fork. You create the pipe twice, once for
the parent process and one for the child process. That makes no sense, the pipe
that the child created cannot be used by the parent. The pipe must already
exists so that the child inherits the file descriptors when the child is
created.
Usually the parent creates the shared memory and the child gets the shmid
from the parent when it does the fork. Otherwise you will have to synchronize
the child and parent. So I would put the creation of the shared memory before
the fork, so that the child inherits the shmid from the parent.
In the line char *n = (char *) shm; the cast is not needed, shm is
already a char*.
In the parent block after the fork, you do wait(NULL); and then proceed to
write into the pipe. That makes no sense and you block both parent and child.
The child blocks on read because the parent hasn't send anything through the
pipe, yet. And the parent blocks on wait, because the child never exits and thus
cannot send anything through the pipe. The parent must first send data
through the pipe, then wait for the child to exit.
In the child block you do scanf("%s", n);, you are not protecting you
against buffer overflows. scanf("%14s", n) would be better. Also you are not
checking if scanf read anything at all. If the user presses
CtrlD then stdin is closed, scanf fails. In that case
n might not be '\0'-terminated and this would lead to undefined behaviour
when the parent tries to print it. So it would be better:
if(scanf("%14s", n) != 1) // avoid buffer overflow
{
fprintf(stderr, "Child: cannot read from stdin\n");
n[0] = 0; // 0-terminating
}
In the parent block after the fork, you do wait twice, why?
Your main is wrong, it should be
int main(int argc, char **argv);
The parent sends the contents of argv[1] to the child through the pipe, but
you fail to check if argv[1] is not NULL. Use this at the start of the
program:
if(argc != 2)
{
fprintf(stderr, "usage: %s string\n", argv[0]);
return 1;
}
So the correct version would be:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <err.h>
#include <sysexits.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#define SHM_SIZE 15
int main (int argc, char **argv) {
pid_t pid; //pid variable of type pid
int shmid; //shared memory id
char *shm; //shared memory name
if(argc != 2)
{
fprintf(stderr, "usage: %s string\n", argv[0]);
return 1;
}
int pipefd[2];
char buff;
// create shared memory before the fork,
// otherwise you will need to syncronize parent
// and child
pipe(pipefd); //creating pipe before the fork
// parent creates shared memory, child inherits shmid
// after fork
shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);
pid = fork(); //creating child process
if (pid < 0) {
fprintf(stderr, "Fork Failed");
return 1; // return -1 would be the same as return 255
} else if (pid == 0) {
shm = shmat(shmid, 0, 0);
char *n = shm; // shm is already a char*
printf("hello i am the child process. my pid is %d. what is your name?: ", getpid());
if(scanf("%14s", n) != 1) // avoid buffer overflow
{
fprintf(stderr, "Child: cannot read from stdin\n");
n[0] = 0; // 0-terminating
}
printf("\n");
///////////////////////////////////////////////////////////////////////////////////////
close(pipefd[1]);
printf("pipe opened on child end");
printf("\n");
printf("Parent sends: ");
fflush(stdout);
while(read(pipefd[0], &buff, 1) > 0) {
write(1, &buff, 1);
}
write(1, "\n", 1);
close(pipefd[0]);
printf("pipe successfully closed");
printf("\n");
exit(EXIT_SUCCESS);
} else {
shm = shmat(shmid, 0, 0);
close(pipefd[0]);
printf("pipe open on parent end");
printf("\n");
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]);
printf("pipe successfully closed");
// not we wait for child to exit
wait(NULL);
printf("\nThis is Child's Parent. My pid is %d. Nice to me you %s.\n", getpid(), shm);
printf("\n");
//////////////////////////////////////////////////////////////////////////////////////
exit(EXIT_SUCCESS);
}
return 0;
}
And the output is:
$ ./b "message to child: stop playing video games!"
pipe open on parent end
hello i am the child process. my pid is 10969. what is your name?: Pablo
pipe opened on child end
Parent sends: message to child: stop playing video games!
pipe successfully closed
pipe successfully closed
This is Child's Parent. My pid is 10968. Nice to me you Pablo.
You are reading and writing from the same end of the pipe you create. Common practice is to read from end [1] and write to end [0]. Tell me if that helps. Additionally, it is also common practice to not have too much going on between the child and parent processes. Attempting to execute code in between segments (parent and child) usually ends up with a segmentation fault, even if your code compiles.

How to Create IPC (Interprocess Communication) C programme to create with two child process

I want to create a IPC c program to create one parent and two child's processes. My code is:
#include <stdio.h>
void main()
{
int pid, status;
pid = fork();
if(pid == -1) {
printf(“fork failed\n”);
exit(1);
}
if(pid == 0) { /* Child */
if (execlp(“/bin/ls”, “ls”, NULL)< 0) {
printf(“exec failed\n”);
exit(1);
}
}
else { /* Parent */
wait(&status);
printf(“Well done kid!\n”);
exit(0);
}
}
I want to show you an other code snippet to create one parent and two child process. This is what I am looking for. Now I want to write shell script for IPC, first take look of this code.
Note: there is an other code with same logic but different process names UP, uc1, uc2 e.g in this way we have two parent VP and UC and there childs vp1 vp2 and uc1 uc2.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_BUF 1024
int main(){
int mypipe_c1[2];
int ret_c1;
char buf_c1[6];
ret_c1 =pipe(mypipe_c1);
int mypipe_c2[2];
int ret_c2;
char buf_c2[6];
ret_c2 =pipe(mypipe_c2);
if(ret_c1 == -1)
{
perror("pipe");
exit(1);
}
pid_t vc1;
pid_t vc2;
vc1 = fork ();
if (vc1 == 0)
{
read(mypipe_c1[0], buf_c1 , 37);
printf("PIPE1 :%s\n", buf_c1);
printf (" vc1 : I'm the child! My pid is (%d)\n", getpid ());
close(ret_c1);
int fd;
char * fifo1 = "/tmp/fifo1";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd = open(fifo1, O_RDONLY);
read(fd, buf, MAX_BUF);
printf("FIFO1: %s\n", buf);
close(fd);
exit(0);
}
if(vc1 < 0)
{
perror ("Ouch! Unable to fork() child process!\n");
exit (1);
}
vc2 = fork ();
if (vc2 == 0)
{
printf ("vc2 : I'm the child! My pid is (%d)\n", getpid ());
read(mypipe_c2[0], buf_c2 , 37);
printf("PIPE2 %s\n", buf_c2);
int fd;
char * fifo2 = "/tmp/fifo2";
/* create the FIFO (named pipe) */
mkfifo(fifo2, 0666);
/* write "Hi" to the FIFO */
fd = open(fifo2, O_WRONLY);
write(fd, " assignment VU 2 ", sizeof(" assignment VU 2 "));
close(fd);
/* remove the FIFO */
unlink(fifo2);
exit(0);
}
else if (vc2 < 0)
{
perror ("Ouch! Unable to fork() child process!\n");
exit (1);
}
printf ("I'm the parent! My pid is (%d)!\n",getpid());
write(mypipe_c1[1], "I am going to close you carry on UC1 \n", 37);
write(mypipe_c2[1], "I am going to close you carry on UC2 \n", 37);
exit(0);
}
Now I want shell script such that VP and UP should be started when users types … script.sh start VP or UP. vc1, vc2, uc1,uc2 should be stoppable only using script.sh stop vc1 or vc2 or uc1 or uc2
script.sh connect command should create two fifo and connect processes as shown in figure.
So you are asking for methods for IPC, with the sample code you provided, I think the best one is the use of pipes.
From the pipe() man page:
A pipe is a unidirectional data channel that can be used for interprocess communication
Basically, it is handled like a pair of file descriptors. First, you must init the pipe, and then create the childs using the fork() call, so both parents and childs share the resource. Then, using write and read methods, you can send data between them.
In this example I create a child which reads some data from the parent process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pid;
char buffer[255];
int fd[2]; // channel 0 for reading and 1 for writing
pipe(fd);
pid = fork();
if(pid == 0) {
close(fd[1]); // close fd[1] since child will only read
read(fd[0], &buffer, sizeof(buffer));
close(fd[0]);
exit(0);
} else { // parent
close(fd[0]) // close fd[0] since parent will only write
// init buffer contents
write(fd[1], &buffer, sizeof(buffer));
close(fd[1]);
}
return 0;
}
As you can see pipe creates a pair of file descriptors, one for writing (number 1) and one for reading (number 0).
In my sample code, the child process closes the writing one, since it will only read, and the parent closes the reading one, since it will only write data.
Note that pipes are unidirectional, so if you want that both the childs and the parent write and read data from it, you should create two pipes (so 4 file descriptors) for each of the childs. An example of how to handle that situation:
int pipeA[2], pipeB[2];
pid = fork();
if (pid == 0) { // child will write to pipeB and read from pipeA
close(pipeA[1]); // closing pipeA writing fd
close(pipeB[0]); // closing pipeB reading fd
write(pipeB[1],&buffer, sizeof(buffer));
read(pipeA[0], &buffer2, sizeof(buffer2));
close(pipeA[0]);
close(pipeB[1]);
exit(1);
} else { // parent will write to pipeA and read from pipeB
close(pipeA[0]); // closing pipeA reading fd
close(pipeB[1]); // closing pipeB writing fd
read(pipeB[0], &buffer, sizeof(buffer));
write(pipeA[1], &buffer2, sizeof(buffer2));
close(pipeA[1]);
close(pipeB[0]);
}
If you want more info about pipes you can check the man page here.
Also, other simple ways of IPC would be the use of Unix Sockets, although I think that for the example you presented pipes will be enough.
You'r code create one parent and one child, not two child, so you need to add another fork into child block :
#include <stdio.h>
void main()
{
int pid,status;
pid = fork();
if(pid == -1) {
printf(“fork failed\n”);
exit(1);
}
if(pid == 0) { /* Child */
fork();// another child
if (execlp(“/bin/ls”, “ls”, NULL)< 0) {
printf(“exec failed\n”);
exit(1);
}
}
else { /* Parent */
wait(&status);
printf(“Well done kid!\n”);
exit(0);
}
}

Child reading from std input and writes to std output

I have a program where the child runs a program but the parent process passes the child a number and the child writes back to the parent a response. However whenever I run the code, it does not give me anything back, so I must be passing or receiving to the child wrong, but I'm not sure how. Any help is appreciated. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int pid;
int n;
char buf[101];
int pfdA[2];
int pfdB[2];
// CREATES FIRST PIPE
if (pipe(pfdA) == -1) {
perror("pipe failed");
exit(-1);
}
// CREATES SECOND PIPE
if (pipe(pfdB) == -1) {
perror("pipe failed");
exit(-1);
}
// FORK()
if ((pid == fork()) < 0) {
perror("fork failed");
exit(-2);
}
if (pid == 0 ) {
// duplicate file descriptor 0 to point to FIRST pipe
dup(pfdA[0]);
// CLOSES ends of FIRST pipe you don't need anymore
close(pfdA[0]);
close(pfdA[1]);
// duplicates file descriptor 1 to point to SECOND pipe
dup(pfdA[1]);
// CLOSES ends of SECOND pipe you don't need anymore
close(pfdB[0]);
close(pfdB[1]);
execlp("./A5_CHILD", "./A5_CHILD", (char *) 0);
perror("execlp");
exit(-3);
}
else {
while( 1 ) {
char NUM[100];
close(pfdA[0]);
close(pfdB[1]);
int r=0;
printf("Enter a Number: ");
fflush(stdout);
scanf("%s", NUM);
// SENDS NUM to Child process
write(pfdA[1], NUM, strlen(NUM));
// READS FROM CHILD THE RESPONSE into the variable buf and
// store the return value from read() into the variable r
r= read(pfdB[0], buf, 100);
if( r > 0 ) {
buf[r] = '\0';
printf("%s\n", buf);
fflush(stdout);
}
else {
printf("[PARENT] Reading from child: read() returned %d\n", r);
break;
}
}
}
return(0);
}
Unless you explicitly close(0), dup(pfdA[0]) almost certainly does not return 0. Try dup2 to specify which descriptor you want as the new one. That is (error checking omitted for brevity):
dup2( pfdA[0], STDIN_FILENO );
close( pfdA[0])
Similarly for stdout.

Resources