UNIX FIFO: the process hangs if I don't close the input side of the fifo
I've just started working with UNIX FIFOs, and I discovered something while experimenting with my first FIFO program. The program works this way: after creating the FIFO, two processes are started using the fork()
function. The child process reads what the father passes to him through the FIFO, and prints it on the screen. The data exchanged is the string specified as an argument. The question is: in the father section, if I forget to close the input side of the FIFO (meaning that I exclude the close(fd)
line) the program would just hang, even if the data between the processes is exchanged correctly. Otherwise, everything works fine and the program terminates withouth hanging. Can someone please explain me why?
Thanks for your patience. Here is the code of the main function:
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("An argument must be specified\n");
return -1;
}
int ret = mkfifo("./fifo.txt", 0644);
char buf;
if(ret < 0)
{
perror("Error creating FIFO");
return -1;
}
pid_t pid = fork();
if(pid < 0)
{
perror("Error creating child process");
return -1;
}
if(pid == 0) /* child */
{
int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */
while(read(fd, &buf, 1) > 0)
{
write(STDOUT_FILENO, &buf, 1开发者_如何学Python);
}
write(STDOUT_FILENO, "\n", 1);
close(fd);
return 0;
}
else /* father */
{
int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */
write(fd, argv[1], strlen(argv[1]));
close(fd);
waitpid(pid, NULL, 0);
return 0;
}
}
read(2)
blocks until there are characters available or the channel is closed at the other end. The father process must close the pipe in order for the last child read()
to return. If you omit the close(fd)
in the father, the child will block in the read()
until the father exits (closing the pipe automatically) but father will hang in waitpid()
until the child exits.
First things first: there are several issues with the code you posted.
- There are no
#include
directives, hence no prototypes in scope for any of the functions you call. C89 requires prototypes for variadic functions such asprintf()
; C99 requires prototypes for all functions. Both C89 and C99 require declarations in scope forO_RDONLY
,O_WRONLY
,STDOUT_FILENO
andNULL
. -1
is not an allowed return value formain()
.- C89 does not allow mixing declarations and statements.
A minor nit: the usual nomenclature is "parent and child", not "father and child".
I have modified your program to correct this issue and improve readability:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
if (argc != 2) {
printf("An argument must be specified\n");
return 1;
}
int ret = mkfifo("./fifo.txt", 0644);
char buf;
if (ret < 0) {
perror("Error creating FIFO");
return 1;
}
pid_t pid = fork();
if (pid < 0) {
perror("Error creating child process");
return 1;
}
if (pid == 0) { /* child */
int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */
while(read(fd, &buf, 1) > 0) {
write(STDOUT_FILENO, &buf, 1);
}
write(STDOUT_FILENO, "\n", 1);
close(fd);
return 0;
} else { /* parent */
int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */
write(fd, argv[1], strlen(argv[1]));
close(fd);
waitpid(pid, NULL, 0);
return 0;
}
}
But most importantly, you did not mention what operating system and compiler you are using.
I am unable to reproduce the issue, and I suspect it may be related to one of the issues listed above.
精彩评论