In my understanding, according to the https://linux.die.net/man/3/mkfifo,
I got an implication that I must have reader and writer file, in order to
utilize the pipe file. The source below is the writer file,
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
int main(){
int fd;
char *myfifo = "./myfifo";
mkfifo(myfifo, 0777);
fd = open(myfifo, O_WRONLY);
int PID = fork();
if(PID == 0){
execl("./reader.o", "reader", (char*)NULL);
}
write(fd, "Rock and roll baby\0", sizeof("Rock and roll baby"));
close(fd);
unlink(myfifo);
return 0;
}
and the source being provided below is for the reader file.
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_BUF 1024
int main(){
int fd;
char* myfifo = "./myfifo";
char buf[MAX_BUF];
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAX_BUF);
write(STDOUT_FILENO, buf, MAX_BUF);
close(fd);
exit(EXIT_SUCCESS);
return 0;
}
When run the executable for the writer file, the command prompt goes into
halt, after printing a newline. My assumption for this problem is because the
open() in the writer file is not being able to detect the pipe file,
is that the case?
Thank you.
I suggest that you should create the FIFO before the fork, but only open the FIFO after the fork. This avoids an assortment of problems. For the most part, I've used write()
to report errors to standard error; it isn't as convenient as using fprintf(stderr, …)
though.
Note that the writer writes a null byte at the end of the message. The reader gets the null byte, but overwrites it with a newline before writing the resulting character array (it is no longer a string; strings have a terminal null byte at the end) to standard output. If the code used <stdio.h>
to write the data (e.g. printf("%s\n", buf)
), it wouldn't need to replace the null byte with a newline.
writer.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef READER
#define READER "./reader"
#endif
int main(void)
{
char *myfifo = "./myfifo";
if (mkfifo(myfifo, 0777) != 0)
{
write(STDERR_FILENO, "Failed to create FIFO\n",
sizeof("Failed to create FIFO\n") - 1);
}
int PID = fork();
if (PID == 0)
{
execl(READER, "reader", (char *)NULL);
write(STDERR_FILENO, "Failed to execute reader\n",
sizeof("Failed to execute reader\n") - 1);
exit(EXIT_FAILURE);
}
if (PID < 0)
{
write(STDERR_FILENO, "Failed to fork\n",
sizeof("Failed to fork\n") - 1);
exit(EXIT_FAILURE);
}
int fd = open(myfifo, O_WRONLY);
if (fd < 0)
{
write(STDERR_FILENO, "Failed to open FIFO for writing\n",
sizeof("Failed to open FIFO for writing\n") - 1);
unlink(myfifo);
exit(EXIT_FAILURE);
}
write(fd, "Rock and roll baby", sizeof("Rock and roll baby"));
close(fd);
unlink(myfifo);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child %d exited with status 0x%.4X\n", corpse, status);
return 0;
}
reader.c
#include <fcntl.h>
#include <unistd.h>
#define MAX_BUF 1024
int main(void)
{
char* myfifo = "./myfifo";
int fd = open(myfifo, O_RDONLY);
if (fd < 0)
write(STDERR_FILENO, "Failed to open FIFO for reading\n",
sizeof("Failed to open FIFO for reading\n")-1);
else
{
char buf[MAX_BUF];
int nbytes = read(fd, buf, MAX_BUF);
if (nbytes > 0)
{
buf[nbytes-1] = '\n';
write(STDOUT_FILENO, buf, nbytes);
}
close(fd);
}
return 0;
}
Rock and roll baby
Child 43734 exited with status 0x0000