http://www.cnblogs.com/nufangrensheng/p/3515035.html中曾将系统调用分成“低速”系统调用和其他系统调用两类。低速系统调用是可能会使进程永远阻塞的一类系统调用,它们包括下列调用:

  • 如果某些文件类型(例如管道、终端设备和网络设备)的数据并不存在,则读操作可能会使调用者永远阻塞。
  • 如果数据不能立即被上述同样类型的文件接受(由于在管道中无空间、网络流控制等),则写操作也会使调用者永远阻塞。
  • 在某种条件发生之前,打开某些类型的文件会被阻塞(例如打开一个终端设备可能需等到与之连接的调制解调器应答;又例如在没有其他进程已用读模式打开该FIFO时,若以只写模式打开FIFO,那么也要等待)。
  • 对已经加上强制性记录锁的文件进行读、写。
  • 某些ioctl操作。
  • 某些进程间通信函数。

虽然读、写磁盘文件会使调用者在短暂时间内阻塞,但并不能将与磁盘I/O有关的系统调用视为“低速”。

非阻塞I/O使我们可以调用open、read和write这样的I/O操作,并使这些操作不会永远阻塞。如果这种操作不能完成,则调用立即出错返回,表示该操作如继续执行将阻塞。

对于一个给定的描述符有两种方法对其指定非阻塞I/O:

(1)如果调用open获得描述符,则可指定O_NONBLOCK标志http://www.cnblogs.com/nufangrensheng/p/3497789.html)。

(2)对于已经打开的一个描述符,则可调用fcntl,由该函数打开O_NONBLOCK文件状态标志http://www.cnblogs.com/nufangrensheng/p/3500350.html,其中,程序清单3-5中的函数可用来为一个描述符打开任一文件状态标志)。

系统V的早期版本使用标志O_NDELAY指定非阻塞方式。在这些版本中,如果无数据可读,则read返回值0。而UNIX系统又常将read返回值0解释为文件结束,两者有所混淆。因此POSIX.1提供了一个名字和语义都与O_NDELAY不同的非阻塞标志。确实,在系统V的早期版本中,当从read得到返回值0时,我们并不知道该调用是否阻塞了或已到文件结尾处。POSIX.1要求,对于一个非阻塞的描述符如果无数据可读,则read返回-1,并且errno被设置为EAGAIN。系统V派生的某些平台支持较老的O_NDELAY和POSIX.1的O_NONBLOCK两者。O_NDELAY只是为了向后兼容,不应在新应用程序中使用。

4.3BSD为fcntl提供了FNDELAY标志,其语义也稍有区别。它不只影响描述符的文件状态标志,还将终端设备或套接字的标志更改成非阻塞的,因此不仅影响共享同一文件表项的用户,而且对终端或套接字的所有用户其作用。另外,如果对一个非阻塞描述符的操作不能无阻塞地完成,那么4.3BSD返回EWOULDBLOCK。现今,基于BSD的系统提供POSIX.1的O_NONBLOCK标志,并且将EWOULDBLOCK定义为与POSIX.1的EAGAIN相同。这些系统提供与其他依从POSIX系统相一致的非阻塞语义。文件状态标志的更改影响同一文件表项的所有用户,但与通过其他文件表项对同一设备的访问无关(参加图3-1http://www.cnblogs.com/nufangrensheng/p/3498509.html和图3-3http://www.cnblogs.com/nufangrensheng/p/3498736.html)。

实例

程序清单14-1是一个非阻塞I/O的实例,它从标准输入读500 000字节,并试图将它们写到标准输出上。该程序先将标准输出设置为非阻塞的,然后用for循环进行输出,每次write调用的结果都在标准出错上打印。函数clr-fl类似于程序清单3-5(http://www.cnblogs.com/nufangrensheng/p/3500350.html)中的set_fl,但与set_fl的功能相反,它清除1个或多个标志位。

程序清单14-1 长的非阻塞write

  1. #include "apue.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4.  
  5. char buf[];
  6.  
  7. extern void set_fl(int, int);
  8. extern void clr_fl(int, int);
  9.  
  10. int
  11. main(void)
  12. {
  13. int ntowrite, nwrite;
  14. char *ptr;
  15.  
  16. ntowrite = read(STDIN_FILENO, buf, sizeof(buf));
  17. fprintf(stderr, "read %d bytes\n", ntowrite);
  18.  
  19. set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */
  20.  
  21. ptr = buf;
  22. while(ntowrite > ) /* 这种形式的循环称为轮循,在多用户系统上它浪费了CPU时间。*/
  23. {
  24. errno = ;
  25. nwrite = write(STDOUT_FILENO, ptr, ntowrite);
  26. fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);
  27.  
  28. if(nwrite > )
  29. {
  30. ptr += nwrite;
  31. ntowrite -= nwrite;
  32. }
  33. }
  34. clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */
  35.  
  36. exit();
  37. }

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

高级I/O之非阻塞I/O的更多相关文章

  1. Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】

    转自:http://blog.csdn.net/jacobywu/article/details/7475432 阻塞型I/O和非阻塞I/O 阻塞:休眠 非阻塞:异步通知 一 休眠 安全地进入休眠的两 ...

  2. C#学习笔记之线程 - 高级主题:非阻塞同步

    非阻塞同步 - Nonblock Synchronization 前面提到,即使在简单的赋值和增加一个字段的情况下也需要处理同步.尽管,使用锁可以完成这个功能,但是锁必定会阻塞线程,需要线程切换,在高 ...

  3. UNIX环境高级编程——非阻塞设置

    非阻塞I/O使我们可以调用open.read和write这样的I/O操作,并使这些操作不会永远阻塞.如果这种操作不能完成, 则调用立即出错返回,表示该操作如继续执行将阻塞. 对于一个给定的描述符有两种 ...

  4. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  5. 网络IPC:套接字之非阻塞和异步I/O

    通常,recv函数没有数据可用时会阻塞等待.同样地,当套接字输出队列没有足够空间来发送消息时函数send会阻塞.在套接字非阻塞模式下,行为会改变.在这种情况下,这些函数不会阻塞而是失败,设置errno ...

  6. linux非阻塞的socket EAGAIN的错误处理

    http://blog.csdn.net/tianmohust/article/details/8691644 在Linux中使用非阻塞的socket的情形下. (一)发送时 当客户通过Socket提 ...

  7. Windows I/O模型、同步/异步、阻塞/非阻塞

    转载自:http://www.cppblog.com/tx7do/articles/5954.html 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.按照这个定义,其实 ...

  8. 五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O

    五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O 五种I/O 模式:[1]        阻塞 I/O          ...

  9. Android NIO(Noblocking I/O非阻塞I/O)小结

    参考:http://www.cnblogs.com/cpcpc/archive/2011/06/27/2123009.html 对于Android的网络通讯性能的提高,我们可以使用Java上高性能的N ...

随机推荐

  1. 【LeetCode 209】Minimum Size Subarray Sum

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  2. 解决虚拟机ssh连接出错connection refused

    在安装操作系统之后,使用ssh连接,发现直接报错connection refused. 检查虚拟机的连接方式,在使用host only的方式的时候,必须接入网线,不然的网卡是不活动的,从而不能使用ss ...

  3. 关于javascript模式一书中var white = new Array(256).join(“ ”)

    直接进入正题 var white = new Array(256).join(" ") 运行后,我们会发现white.length的长度是255,这个是为什么呢?书上没有给出解答, ...

  4. kendoui-在线文本编辑器

    文本编辑器用过很多,fckeditor是我之前用的最多的,但是问题也有很多,诸如安全问题,浏览器兼容问题..所以最近也一直在找替代产品,正好在研究kendo,所以就尝试了下kendo提供的edit控件 ...

  5. Spark系列(七)Master中的资源调度

    资源调度 说明: Application的调度算法有两种,分别为spreadOutApps和非spreadOutApps spreadOutApps 在spark-submit脚本中,可以指定要多少个 ...

  6. leetcode@ [336] Palindrome Pairs (HashMap)

    https://leetcode.com/problems/palindrome-pairs/ Given a list of unique words. Find all pairs of dist ...

  7. java动态代理与老式AOP实现

    JAVA的动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会 ...

  8. Spring EL Lists, Maps example

    In this article, we show you how to use Spring EL to get value from Map and List. Actually, the way ...

  9. 怎样提交FIREDAC数据集的DELTA到中间件然后保存进数据库

    你可以在客户端序列FireDAC数据集的DELTA , 将序列后的STREAM发送给中间件, 中间件的TFDQuery或TFDMemTable调用LOADFROMSTREAM()方法加载流, 然后调用 ...

  10. HDU 4463 Outlets (最小生成树)

    题意:给定n个点坐标,并且两个点已经连接,但是其他的都没有连接,但是要找出一条最短的路走过所有的点,并且路线最短. 析:这个想仔细想想,就是应该是最小生成树,把所有两点都可以连接的当作边,然后按最小生 ...