在输入输出系统一文中介绍了系统内核操作IO设备的机制。 我们了解到内核可以直接访问IO设备, 用户进程无法IO设备。
就是说IO操作需要分为两个过程, 内核从IO设备读取数据保存到内核空间, 将数据由内核空间拷贝到用户空间。
IO调用可以分为同步调用和异步调用。同步调用要求主线程采用轮询等机制主动检查IO状态; 异步调用下主线程发出IO调用并立即返回, 在IO完成后通过回调函数等通知机制通知主线程.
阻塞IO与非阻塞IO的区别在于等待内核从外部设备读取数据时主线程是否阻塞。
由此可见, 同步和异步调用关心的是消息通信机制,阻塞和非阻塞IO关心的是IO操作过程中主线程的状态。
Linux的IO模型中Non-Blocking, Multiplexing IO, Signal Driven IO通过同步调用实现了非阻塞调用.
Blocking IO
应用程序执行一次IO调用, 导致应用程序阻塞, 直到内核准备好数据报并完成拷贝后返回.
是最容易理解的一种IO模型.
Non-Blocking IO
主线程执行IO调用, 内核开始准备数据, 用户通过轮询检查数据是否就绪. 若未就绪则继续立即返回继续执行主线程, 若就绪则开始进行拷贝, 拷贝过程中用户线程被堵塞.
主线程在执行轮询后立即返回,说明这是非阻塞IO。但需要主线程主动轮询获得IO操作状态, 所以仍属于同步IO。
Multiplexing IO
select和epoll即是此IO模型的典型实现,一次IO操作中包含两次调用两次返回
多路IO复用可以实现对多个IO端口的监听, 内核一旦发现主线程指定的一个或者多个IO数据拷贝就绪, 它就通知主线程将数据拷贝到用户空间.
该模型中select或epoll等系统调用在内核态轮询IO状态。
Signal Driven IO (SIGIO)
信号驱动IO在等待数据阶段采用了不同的等待方式.