So I recently had an exam in a class about operating systems and it had asked me to write a program using pipe(). This program was intended to send and receive data through the pipe so that regardless of which file was run, the output would be the same.
The output should be the following.
Hello (from child) 1
Hello (from parent)
Hello (from child) 2
The template code was given as follows. (I could not change this code, I was only to insert code to make it work). No creativity... I know.
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
int main() {
pid_t pid;
char buf[32];
if ((pid = fork()) < 0) {
puts("Error");
} else if(pid == 0) { //child
fprintf(stdout, "Hello (from child) 1\n");
fprintf(stdout, "Hello (from child) 2\n");
fflush(stdout);
}
else {
fprintf(stdout, "Hello (from parent)\n");
}
}
After some time my conclusion was the following. But after executing nothing printed. (I couldn't test it because it was a paper exam but I tested it after). Also, I was under a time crunch so I know the mistakes are probably frequent.
I added the User Start
and User End
to show where I could change the code. Any help would be appreciated.
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
int main() {
pid_t pid;
char buf[32];
// User Start
int fds[2];
pipe(fds);
close(1);
dup(fds[1]);
// User End
if ((pid = fork()) < 0) {
puts("Error");
} else if(pid == 0) { //child
// User Start
// User End
fprintf(stdout, "Hello (from child) 1\n");
// User Start
write(fds[1],"Hello (from child) 1\n",21);
read(fds[0],buf,21);
write(fds[1],"Hello (from child) 2\n",21);
// User End
fprintf(stdout, "Hello (from child) 2\n");
// User Start
// User End
}
else {
// User Start
read(fds[0],buf,21);
// User End
fprintf(stdout, "Hello (from parent)\n");
// User Start
write(fds[1],"Hello (from parent)\n",21);
read(fds[0],buf,21);
// User End
}
}
UPDATE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
int main()
{
pid_t pid;
char buf[32];
int returnstatus1;
int fds[2];
returnstatus1 = pipe(fds);
printf("Return status = %d\n",returnstatus1); //check if pipe is created or not
if(returnstatus1 == -1)
{
printf("Pipe 1 could not be created\n");
return 1;
}
if((pid = fork()) < 0)
{
puts("ERROR");
}
//child
else if(pid == 0)
{
fprintf(stdout,"hello (from child) 1\n");
close(fds[0]);
write(fds[1],"hello (from child) 1\n",21);
close(fds[1]);
read(fds[0],buf,21);
fprintf(stdout,"hello (from child) 2\n");
close(fds[0]);
write(fds[1],"hello (from child) 2",21);
}
//parent
else
{
close(fds[1]);
read(fds[0],buf,21);
fprintf(stdout,"hello (from parent)\n");
close(fds[0]);
write(fds[1],"hello (from parent)\n",21);
close(fds[1]);
read(fds[0],buf,21);
}
return 0;
}
The use of pipes for synchronization is slightly unorthodox, but it's perfectly doable. You have to remember that reading from an empty pipe is blocking — it waits until something has written to it.
Since it's clearer that way, I'll show the parent first, not the child. Of course it doesn't matter in which order you put the if
branches — you can adapt it to your exam's format, and I strongly encourage you to do so in order to get a hang of it.
With that in mind, we go ahead:
#include <stdio.h>
#include <unistd.h>
int main (void) {
pid_t pid;
char buf;
int parent_pipes[2];
int child_pipes[2];
pipe(child_pipes);
pipe(parent_pipes);
if ((pid = fork()) < 0)
puts("Error");
else if (pid) {
// parent first!
// wait for the child to write something into the pipe...
read(*child_pipes, &buf, 1);
// and now write to stdout, and tell the child that we're ready
fprintf(stdout, "Hello (from parent)\n");
fflush(stdout);
write(parent_pipes[1], "R", 1); // it doesn't matter what we write; we have to write anything
} else {
// and now the child
// output and flush...
fprintf(stdout, "Hello (from child) 1\n");
fflush(stdout);
// ...and tell the parent that we're ready
write(child_pipes[1], "R", 1); // write end of the pipe
// now wait!
read(*parent_pipes, &buf, 1); // read end of the pipe
fprintf(stdout, "Hello (from child) 2\n");
}
return 0;
}