我有一个非常简单的基本程序,有两个过程,第一个是parent
,第二个是child
。
子进程应该写一些东西到FIFO
。完成所有写作业后(孩子终止后)。然后父进程应读取所有FIFO
文件并打印到stdout
。
所以我想,我需要wait(NULL);
为parent
。所以parent
将等到child
终止。但child
也被封锁,因为写作和封锁阅读此写。所以这两个进程都互相等待,我认为发生了死锁。
我的程序是这样的:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
int writeSomeStuffToFifo ();
void printAllFifo ();
char * myfifo = "myfifo";
int main(int argc, char **argv) {
int pid=0;
int childPid=-1;
int status;
pid=fork();
if ((pid = fork()) < 0){
perror("fork() error");
}
else if (pid == 0) {
writeSomeStuffToFifo ();
exit(1);
}
else do {
if ((pid = waitpid(pid, &status, WNOHANG)) == -1)
perror("wait() error");
else if (pid == 0) {
//child running
printf("child running\n");
}
else {
if (WIFEXITED(status)){
printf("child is terminated\n");
printAllFifo();
}
else{
printf("child did not exit successfully\n");
}
}
} while (pid == 0);
return 0;
}
int writeSomeStuffToFifo (){ //child process will run this function
int fd;
mkfifo(myfifo, 0666);
fd = open(myfifo, O_WRONLY);
write(fd,"foo1\n",strlen("foo1\n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo2\n",strlen("foo2\n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo3\n",strlen("foo3\n"));
close(fd);
}
void printAllFifo (){ //parent process will run this function
int fd=open(myfifo, O_RDONLY);
char* readBuffer=(char*)malloc((strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"))*sizeof(char));
read(fd, readBuffer, strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"));
printf("%s\n",readBuffer );
close(fd);
}
mkfifo()
创造了一个有限大小的管道。您不应该在父进程中等待子进程完成才能读取,您应该在父进程中不断阅读,同时检查子进程是否已经终止。
您可以使用ulimit -p
来读取Linux系统中管道的默认大小。该数字是512的乘法,因此值8表示4096字节。
使用pipe()
比mkfifo()
更适合于任务,因为您实际上不需要命名管道。这将为您提供2个fds,一个用于读取,一个用于写入。在父代码中关闭write fd,在子代码中关闭read fd,然后你可以从父代码中的管道开始读取,直到它返回一个值<= 0.这意味着子进程已经终止(并且管道已关闭以便书写)。那么你只需要从父代码中调用waitpid()
来收集已终止的子进程。