免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1213 | 回复: 0
打印 上一主题 下一主题

非阻塞IO [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-04 20:04 |只看该作者 |倒序浏览
非阻塞I/O使我们可以调用不会永远阻塞的I/O操作,例如read和write。如果  这种操作不能完成,则立即出错返回,表示该操作如继续执行将继续阻塞下去。  
对于一个给定的描述符有两种方法对其指定非阻塞I/O:  
1. 如果是调用open以获得该描述符,则可指定O_NONBLOCK标志。
2. 对于已经打开的一个描述符,则可调用fcntl,对其打开O_NONBOCK文件状态标 志
可见阻塞还是非阻塞与read、write等系统调用和文件(如普通的磁盘文件或socket)无关,而是与是否用上面那两个方法设置文件描述符的属性O_NONBLOCK有关.默认情况下,文件的IO是阻塞IO,除非用上面两个方法设置非阻塞标志。  
下面的程序是一个非阻塞I/O的实例,它从标准输入读100,000字节,并试图将它们 写到标准输出上。该程序先将标准输出设置为非阻塞的,然后用for循环进行输出  ,每次写的结果都在标准出错上打印。
               
               
                #include        sys/types.h>  
#include        errno.h>  
#include        fcntl.h>  
#include        "ourhdr.h"  
char    buf[100000];  
int  
main(void)  
{  
        int             ntowrite, nwrite;  
        char    *ptr;  
        ntowrite = read(STDIN_FILENO, buf, sizeof(buf));  
        fprintf(stderr, "read %d bytes\n", ntowrite);  
        set_fl(STDOUT_FILENO, O_NONBLOCK);      /* set nonblocking */  
        for (ptr = buf; ntowrite > 0; ) {  
                errno = 0;  
                nwrite = write(STDOUT_FILENO, ptr, ntowrite);  
                fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);  
                if (nwrite > 0) {  
                        ptr += nwrite;  
                        ntowrite -= nwrite;  
                }  
        }  
        clr_fl(STDOUT_FILENO, O_NONBLOCK);      /* clear nonblocking */  
        exit(0);  
}   
标准输出是普通文件,则可以期望write只执行一次。  
$a.out temp.file                                        先试一普  文件  
read 100000 bytes  
nwrite-100000, errno=0                                                  一次写  
$ls -l temp.file                                                          验输出文件长度  
-rw-rw-r-1 stevens 100000 Nev 21 16:27 temp.file  
但是,若标准输出是终端,则可期望write有时会返回一个数字,有时则出错返回  
$ a.out stderr.out                                     向终端输出  大量输出至终端  
$ cat stderr.out  
read 100000 bytes  
nwrite=8192, errno=0  
nwrite=8192, errno=0  
nwrite=-1, errno=11  
…  
nwrite=4096,errno=0  
nwrite=-1, errno=11  
…  
nwrite=4096,errno=0  
nwrite=-1, errno=11  
…  
nwrite=4096,errno=0  
nwrite=-1, errno=11  
…  
nwrite=-1, errno=11  
…  
nwrite=4096,errno=0                                                     …等等  
    在该系统上,errno11是EAGAIN((或者EWOULDBLOCK,这两个宏定义的值相同))。此系统上的终端驱动程序总是一次接收4096或8192字节。在另一个系统上,前三个write返回2005,1822和1811,然后是96次出错 返回,接着是返回1864等等。  每个write能写多少字节是依赖于系统的。 在此实例中,程序发出了数千个write调用,但是只有20个左右是真正输出数据的  ,其余的则出错返回。这种形式的循环称为轮询,在多用户系统上它浪费了CPU时 间。 ,调用者应该试着再读一次(again),这样可以同时监视多个设备。
#include "apue.h"
#include fcntl.h>
void
set_fl(int fd, int flags)                     /* flags are file status flags to turn on */
{
    int        val;
    if ((val = fcntl(fd, F_GETFL, 0))  0)
        err_sys("fcntl F_GETFL error");
    val |= flags;                            /* turn on flags */
    if (fcntl(fd, F_SETFL, val)  0)
        err_sys("fcntl F_SETFL error");
}
void
cli_fl(int fd, int flags)                     /* flags are file status flags to turn off*/
{
    int        val;
    if ((val = fcntl(fd, F_GETFL, 0))  0)
        err_sys("fcntl F_GETFL error");
    val &= ~flags;                            /* turn off flags */
    if (fcntl(fd, F_SETFL, val)  0)
        err_sys("fcntl F_SETFL error");
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103462/showart_2086453.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP