O_NONBLOCK模式下写fifo的注意事项

后台网络通信框架一般采用fifo来作为事件通知的机制:创建一个fifo,然后以非阻塞读和非阻塞写的方式打开fifo,然后把fd加到epoll里面,作为通知网络事件的fd.

在这里有个隐晦的问题容易被忽视.fifo在以非阻塞模式打开时,必须先打开读,然后打开写.不然会报错No such device or address.即如下代码所示是正确的

#define FIFO_FILE "/tmp/fifo.xxx"

#define FIFO_MODE FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH



mkfifo(FIFO_FILE, FIFO_MODE);

int readfd  = open(FIFO_FILE, O_RDONLY | O_NONBLOCK, 0);

int writefd = open(FIFO_FILE, O_WRONLY | O_NONBLOCK, 0);

上述代码中的两个open不能反过来,不然会报错: No such device or address

注意到这种情况,那即使以后我们写代码是在两个进程间通过fifo来通信,也不用关心以写的方式打开fifo之前,fifo是否已经以读的方式打开,因为我们可以设置一个dummy fd,如下所示:

int dummyfd = open(FIFO_FILE, O_RDONLY | O_NONBLOCK, 0);

int writefd = open(FIFO_FILE, O_WRONLY | O_NONBLOCK, 0);

敢兴趣的朋友可以把下面的代码复制过去,看看输出结果:

1/注释L18

2/不注释L18

 1 #include <unistd.h>                                                                                 

 2 #include <sys/types.h>                                                                              

 3 #include <sys/stat.h>                                                                               

 4 #include <fcntl.h>                                                                                  

 5                                                                                                     

 6 #include <errno.h>                                                                                  

 7 #include <stdio.h>                                                                                  

 8 #include <string.h>                                                                                 

 9                                                                                                     

10 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH                         

11 #define FIFO_FILE "/tmp/fifo.test_nonblock_write"                                                   

12                                                                                                     

13 int main(void)                                                                                      

14 {                                                                                                   

15     mkfifo(FIFO_FILE, FILE_MODE);                                                                   

16     fprintf(stderr, "mkfifo, errno=%d, error=%s\n", errno, strerror(errno));                        

17                                                                                                     

18     //open(FIFO_FILE, O_RDONLY|O_NONBLOCK, 0);                                                      

19     fprintf(stderr, "open(O_RDONLY), errno=%d, error=%s\n", errno, strerror(errno));                

20                                                                                                     

21     open(FIFO_FILE, O_WRONLY|O_NONBLOCK, 0);                                          

22     fprintf(stderr, "open(O_WRONLY), errno=%d, error=%s\n", errno, strerror(errno));                

23                                                                                                     

24     unlink(FIFO_FILE);                                                                          

25                                                                                                     

26     return 0;                                                                                       

27 }

 

你可能感兴趣的:(block)