Chinaunix首页 | 论坛 | 博客
  • 博客访问: 608632
  • 博文数量: 126
  • 博客积分: 4379
  • 博客等级: 上校
  • 技术积分: 2110
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-06 22:35
文章分类

全部博文(126)

文章存档

2012年(5)

2011年(3)

2010年(2)

2009年(116)

分类: LINUX

2009-07-14 23:45:49

 

 

 

管道或FIFO的open、read、write以及相关的阻塞与非阻塞是这一部分的难点,这些概念不是很难,但是揉在一起就让人感觉理不清头绪, 仔细研究了这一部分很多遍,总算有点头绪。借用《UNP》上的表:

 

当前操作

Pipe或FIFO

现有操作

返回

阻塞

O_NONBLOCK

Open

(FIFO

O_RDONLY)

 

 

Open(FIFO, O_WRONLY)

成功

成功

Open(FIFO,

O_RDONLY)或无open

阻塞到

Open(FIFO, O_WRONLY)

成功

Open

(FIFO

O_WRONLY)

 

 

Open(FIFO

O_RDONLY)

成功

成功

Open(FIFO, O_WRONLY)或

无open

 

阻塞到

Open(FIFO,O_RDONLY)

ENOXIO

从空pipe或空FIFO

Read

 

管道或FIFO打开来写

阻塞到pipe或FIFO中有数据

Pipe或FIFO不再为写打开

EAGAIN

管道或FIFO不是打开来写

返回0(EOF)

返回0(EOF)

往管道或FIFO write

 

 

管道或FIFO打开来读

 

 

管道或FIFO不是打开来读

SIGPIPE

SIGPIPE

 

1、open Open(FIFO, O_WRONLY)与Open(FIFO, O_RDONLY)要成对出现,否则就会阻塞对于设置了O_NONBLOCK标志的,Open(FIFO, O_WRONLY)之前必须有Open(FIFO, O_RDONLY),否则会返回ENOXIO。 这一点都比较好理解。

2、read and write 这一点比较乱,还是用代码说话比较好,下面是代码片段。

 

       if ( (childpid = Fork()) == 0) {            /* child */

              readfd = Open(FIFO1, O_RDONLY, 0);

              writefd = Open(FIFO2, O_WRONLY, 0);

              …

//(4)

       Close(readfd);                                    //管道或FIFO不是打开来读

//

                                                                             //// 从空pipe或空FIFORead

              if ( (n = Read(readfd, buff, MAXLINE)) == 0)                  //(2)返回EOF

              err_quit("end-of-file while reading pathname");           //(1)阻塞

              …

              exit(0);

       }

              /* 4parent */

       writefd = Open(FIFO1, O_WRONLY, 0);

       readfd = Open(FIFO2, O_RDONLY, 0);

       …

       Fgets(buff, MAXLINE, stdin);

       …

// (2)

       Close(writefd);                                                               //管道或FIFO不是打开来写

//

//(1)                                                                                     //管道或FIFO打开来写

       Len = 0;

//

       Write(writefd, buff, len);                                                 //(4)产生SIGPIPE

 

标记(1)、(2)、(3)、(4)是添加的代码实现上面表格中标记的功能。第(3)中情况,要注意写不能溢出缓冲区就可以了,否则情况就难以预知了。

 

不知道这样能不能看明白,说明一下:

(1)FIFO打开来写的,但写入0字节,模拟使FIFO为空,子进程Read就会阻塞。

(2)close(writefd)使FIFO不再为写打开, 子进程Read会返回EOF。

(4)子进程close(readfd)使FIFO不再打开来读, 父进程Write会产生SIGPIPE。

 

阅读(2189) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~