我不会编写使用2个管道在父子进程之间传递值的程序。代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
int mkfifo(const char *path, mode_t mode);
int main(int argc, char **argv)
{
int fd,df,val;
char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
char * myfifo2 = "/tmp/myfifo2";
mkfifo(myfifo2, 0666);
pid_t c=fork();
if(c==0){
df = open(myfifo2, O_RDONLY);
read(df, &val, sizeof(val));
close(df);
val= val+10;
df = open(myfifo2, O_WRONLY);
write(df, &val, sizeof(val));
fd = open(myfifo, O_WRONLY); //if i put this write first print works and program finishes
write(fd, &val, sizeof(val));
}
if(c>0)
{
val=1;
df = open(myfifo2, O_WRONLY);
write(df, &val, sizeof(val));
fd = open(myfifo, O_RDONLY);
read(fd, &val, sizeof(val));
printf("val is %d \n",val);
}
}
对子项的第一次读取会等待父项在fifo文件中写入val,然后将新的val写入此fifo文件中,然后将值写入第二个文本文件中。在父项的代码中读取会等待此过程因此,我想要的全部是父进程仅在子进程已在myfifo2文件中写入val后才执行打印。这就是我使用的第二个命名管道的目的。但是,此代码得到了卡住了,什么也没打印。我注意到,如果我改变子进程中两次写入的顺序,它可以工作,但不能满足我所需要的上述要求。为什么会这样,我该如何解决呢?
答案 0 :(得分:2)
虽然命名管道 可以用于缓冲(如您所愿),但要依靠它来不阻塞程序(因为这就是您所需要的,死锁 )是一种非常糟糕的做法。
此外,它还带有一些警告:
为了获得“缓冲”效果,需要打开管道的两端(man 7 fifo
)
必须先在两端打开FIFO(读取和写入),然后才能传递数据。通常,打开FIFO块,直到另一端也打开。
一旦管道达到其容量,写入最终将被阻塞。该大小取决于系统,但可以通过F_SETPIPE_SZ
fcntl
进行设置。而且:
请注意,由于管道缓冲区的页面是 数据写入管道时使用的字节数 可写的字数可能小于标称大小,具体取决于 取决于写入的大小。
因此,您遇到这种情况:
父项(可能甚至可能还没有)在read
上的/tmp/myfifo
中等待。
/tmp/myfifo2
由父级WR_ONLY
打开。
子代调用df = open(myfifo2, O_WRONLY);
,并以/tmp/myfifo2
的身份打开WR_ONLY
。因此,未打开了管道的读取端,因此调用了open
块。
死锁。
要解决此问题,只需以读写方式 在子级中打开myfifo2
。
df = open(myfifo2, O_RDWR); // instead of df = open(myfifo2, O_WRONLY);
IMO,这种通信模式看起来有些奇怪(并且很难理解)。