Reputation: 75
I need to create communication between parent and a forked child using pipes. The parent will send 0, the child will send back 1, the parent will reply 2, etc., until the counter reaches 5. Then both processes will terminate.
I tried to implement this using two pipes:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int fd[2];
int fd2[2];
int val = 0;
// create pipe descriptors
pipe(fd);
pipe(fd2);
// fork() returns 0 for child process, child-pid for parent process.
if (fork() != 0) {
///0. Send: 0
// parent: writing only, so close read-descriptor.
close(fd[0]);
// send the value on the write-descriptor.
val = 0;
resend:
write(fd[1], &val, sizeof(val));
printf("0.Parent(%d) send value: %d\n", getpid(), val);
// close the write descriptor
close(fd[1]);
///3. Receive 1;
close(fd2[1]);
// now read the data
read(fd2[0], &val, sizeof(val));
printf("3.Parent(%d) received value: %d\n", getpid(), val);
// close the read-descriptor
close(fd2[0]);
wait(NULL);
val++;
if (val < 6)
goto resend;
else
return 0;
} else { // child: reading only, so close the write-descriptor
childStart:
wait(NULL);
///1. receive: 0
close(fd[1]);
// now read the data (will block)
read(fd[0], &val, sizeof(val));
printf("1.Child(%d) received value: %d\n", getpid(), val);
// close the read-descriptor
//close(fd[0]);
///2. Send: 1
// parent: writing only, so close read-descriptor.
close(fd2[0]);
// send the value on the write-descriptor.
val = val + 1;
write(fd2[1], &val, sizeof(val));
printf("2.Child(%d) send value: %d\n", getpid(), val);
// close the write descriptor
close(fd2[1]);
if(val <5) {
wait(NULL);
goto childStart;
}
else
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
return 0 ;
}
I get the follow output:
0.Parent(120978) send value: 0
1.Child(120979) received value: 0
2.Child(120979) send value: 1
1.Child(120979) received value: 1
2.Child(120979) send value: 2
1.Child(120979) received value: 2
2.Child(120979) send value: 3
1.Child(120979) received value: 3
2.Child(120979) send value: 4
1.Child(120979) received value: 4
2.Child(120979) send value: 5
3.Parent(120978) received value: 1
0.Parent(120978) send value: 2
3.Parent(120978) received value: 2
0.Parent(120978) send value: 3
3.Parent(120978) received value: 3
0.Parent(120978) send value: 4
3.Parent(120978) received value: 4
0.Parent(120978) send value: 5
3.Parent(120978) received value: 5
How can I make the processes wait for each other's message?
Upvotes: 4
Views: 2726
Reputation: 397
Thera are a lot of problems in your code, i changed a lot of things, the result is this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
int main(int argc, char *argv[])
{
int signo;
pid_t child_pid,parent_pid;
sigset_t newmask;
int fd[2];
int fd2[2];
int val = 0;
// create pipe descriptors
pipe(fd);
pipe(fd2);
// create mask for SIGUSR1
sigemptyset(&newmask);
sigaddset(&newmask,SIGUSR1);
sigaddset(&newmask,SIGUSR2);
sigprocmask(SIG_BLOCK,&newmask,NULL);
parent_pid = getpid();
// fork() returns 0 for child process, child-pid for parent process.
if ((child_pid = fork()) != 0) {
// Close unused file descriptors
close(fd[0]);
close(fd2[1]);
// send the value on the write-descriptor.
for(val = 0; val < 6; val++){
write(fd[1], &val, sizeof(val));
printf("0.Parent(%d) send value: %d\n", getpid(), val);
sigwait(&newmask,&signo);
kill(parent_pid,SIGUSR2);
// now read the data
read(fd2[0], &val, sizeof(val));
printf("3.Parent(%d) received value: %d\n", getpid(), val);
sigwait(&newmask,&signo);
kill(parent_pid,SIGUSR2);
}
return 0;
} else { // child: reading only, so close the write-descriptor
// Closing unused file descriptors
close(fd[1]);
close(fd2[0]);
for(; val <= 5; val++){
// now read the data (will block)
read(fd[0], &val, sizeof(val));
printf("1.Child(%d) received value: %d\n", getpid(), val);
kill(child_pid,SIGUSR1);
sigwait(&newmask,&signo);
// send the value on the write-descriptor.
write(fd2[1], &val, sizeof(val));
printf("2.Child(%d) send value: %d\n", getpid(), val);
kill(child_pid,SIGUSR1);
sigwait(&newmask,&signo);
}
wait(NULL);
return 0;
}
}
Your mistakes:
sigwait()
(https://www.man7.org/linux/man-pages/man3/sigwait.3.html) and kill
(https://www.man7.org/linux/man-pages/man2/kill.2.html),wait(NULL)
in child and in other places where it was uselessoutput:
0.Parent(14956) send value: 0
1.Child(14957) received value: 0
2.Child(14957) send value: 0
3.Parent(14956) received value: 0
0.Parent(14956) send value: 1
1.Child(14957) received value: 1
2.Child(14957) send value: 1
3.Parent(14956) received value: 1
0.Parent(14956) send value: 2
1.Child(14957) received value: 2
2.Child(14957) send value: 2
3.Parent(14956) received value: 2
0.Parent(14956) send value: 3
1.Child(14957) received value: 3
2.Child(14957) send value: 3
3.Parent(14956) received value: 3
0.Parent(14956) send value: 4
1.Child(14957) received value: 4
2.Child(14957) send value: 4
3.Parent(14956) received value: 4
0.Parent(14956) send value: 5
1.Child(14957) received value: 5
2.Child(14957) send value: 5
3.Parent(14956) received value: 5
Upvotes: 2