- 阻塞IO
-
实现:应用进程被阻塞,直到数据从内核缓冲区复制到应用进程缓冲区中才返回。
在阻塞的过程中,其它应用进程还可以执行,因此阻塞不意味着整个操作系统都被阻塞,但是当前进程不能执行任何操作。 -
效率:因为其它应用进程还可以执行,所以不消耗 CPU 时间,这种模型的 CPU 利用率会比较高。
- 非阻塞IO
-
实现:recvfrom重复调用等待返回成功指示,用户进程可以在这个时间执行别的事。
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。 -
效率:由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率比较低。
- IO复用
-
实现:select函数可监听多个事件;
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。 -
效率:如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。
- 信号量
signal函数捕获
- 异步IO
模拟5种IO模型例子:
活动:演唱会;
角色1:小明(粉丝);角色2:售票员;角色3:黄牛;角色4:送票快递员;
同步阻塞:小明从家到售票点买票,售票员告诉小明,票明天才可以售卖,小明直接在售票点等到明天再买票之后回家;这就好像我们去逛街购物,到店里去买衣服的时候,如果没有合适的尺码,需要等到店员从仓库中拿到大小合适衣服,这个期间我们需要在店内等待,知道拿到衣服。
非阻塞IO:小明从家到演唱会现场问售票员买票,但票还没有出来,之后小明走了,去做别的事情,过了几个小时再次来询问是否有票产生,如果还没有继续做别的事情,重复上述操作,直到票可以买了;
IO复用:JAVA----》selector/Linux------》select,poll,eoll
小明想去买演唱会的票,打电话告诉黄牛(selector)帮留意买个票,看什么时候有票通知小明,等到有票了小明花时间去售票点买票;
信号驱动IO:小明想去买演唱会门票,给举办方打电话,帮我留意一下票,可以售票了给我打个电话,我自己来买票;
异步IO:小明给举办方打电话,可以售票了让快递员将票送到家里,小明不用专门自己去买票。