阻塞与非阻塞

  近来遇到一些网络编程方面的问题,涉及到了一些常见的概念,如:阻塞、非阻塞、异步I/O等等,百度的结果是惨不忍睹的,当然这也不能怪百度。没有办法还是得看英文,翻教材。后来发现阻塞和非阻塞的概念也并不难以理解,这篇随笔记录一下自己的见解,欢迎拍砖,希望多多交流。

  进程的状态主要涉及运行态、就绪态和阻塞态等,一个进程逻辑上无法继续执行(例如等待I/O事件时)会被阻塞。实际上OS内部是由一个高级的进程调度程序来管理进程的状态变化以及进程共享CPU的,被阻塞的进程会被调度程序“无视”——除非你的I/O(或其他条件)就绪,然后你转成就绪态,否则就是CPU空转,我都不鸟你(不让你获得CPU)。

  这样一来其实“阻塞”和“非阻塞”的特点就很明显了,阻塞I/O,在阻塞点可以看做暂停了代码的执行,后面的代码只有等I/O需求得到满足后才能继续,这是因为一旦到达阻塞点,进程调度程序直接“无视”被阻塞的进程,I/O完成前该进程是获得不了CPU的。

  对于非阻塞I/O,即使I/O没有就绪,但是此时调用返回了错误,或者抛出了异常,在I/O尚未就绪的这段时间里并没有丧失CPU的使用权,而是继续具有调度获得CPU的权利,所以其后的代码得以继续,也就是程序可以继续运行。

  对于非阻塞I/O,如何在I/O事件完成后继续程序应有的执行流程呢,这催生了两种主要的技术,一种是“等你搞定了告诉我啊”这样的事件驱动机制(异步),另一种是“我会不断问你OK没有”这样的轮询机制(同步),当然,这里的“你”,就是操作系统啦。

 

  更新:

  看到一些文章上面将阻塞、非阻塞、同步、异步四个概念进行了对比,大概意思是:

  • 阻塞、非阻塞 和 同步、异步是独立的概念;
  • 阻塞 / 非阻塞是指相应的一个操作是否会阻塞程序使其无法继续运行,只有一定的条件满足后才能继续;
  • 同 / 异步则是指程序获取条件是否满足这个信息的方式,如果是自己不断地去打听(向内核),就是同步,如果是内核等一切都处理好了通知程序,就是异步。

  所以异步非阻塞I/O就是I/O请求到来时程序并不阻塞,同时可以指定一个回调函数,当内核响应需要的资源就绪后,用回调函数去 handle 后续的操作。而异步阻塞I/O,例如 select 机制,同样是由内核通知程序哪些 fd 已经OK,但是程序会阻塞在 select() 调用上,而非同步阻塞I/O中的I/O操作上。

 

posted @ 2015-06-23 01:23  王智愚  阅读(638)  评论(0编辑  收藏  举报