【Linux】高级I/O
IO模型
- 阻塞性IO(循环等待事件发生)
- 非阻塞型IO(轮询检测)
- 信号驱动型IO(事件发生时会发送信号)
- 多路转接型IO(存在多条事件检测并拷贝)
- 异步IO
阻塞型IO
非阻塞型IO(轮询检测)
阻塞型IO与非阻塞型IO的唯一区别是在等待内核将数据准备完成的阶段,阻塞型IO会让recvfrom进程挂起,等待数据准备好的进程信号,非阻塞型IO会立即返回,然后被应用进程循环调用,但是轮询要频繁的访问内核中的文件描述符等资源,非常消耗cpu的资源,一般不这样做。
信号驱动型IO
让应用进程在 “内核准备数据” 阶段不阻塞(可并行处理其他任务),仅当内核完成数据准备后,通过 “信号” 主动通知应用进程,再调用读/写程序,将数据从内核复制到用户空间。
- 通过SIGIO信号,注册一个函数,然后绑定文件描述符
- 当文件描述符中数据可以准备读写时(数据被存入了内核缓冲区),OS通过SIGIO信号调用注册的函数,然后执行read/write函数,将数据从内核中拷贝到用户空间。
信号驱动型IO,也是同步IO的一种,虽然在等待数据准备完成是异步的,但是将数据从内核拷贝到用户,还是应用进程在执行,并且需要等待数据拷贝完成才能执行后续逻辑。
异步IO
AIO是内核提供的系统调用,不是一个内核进程,不占用 CPU 时间片,其请求处理逻辑(如调度 IO 设备、数据传输)是 “附着” 在 IO 设备驱动的中断上下文或内核工作队列(Work Queue)中执行的。AIO是只有被动触发才会调用,否则不会占用任何资源。
IO多路转接
整个IO流程分为两步
数据等待+数据拷贝
,阻塞型IO、非阻塞型IO和信号驱动型IO,唯一的差别都是在数据等待
阶段,但它们数据拷贝
阶段都是进程执行,所以它们都是同步IO。
而异步IO在这两个阶段都不是进程处理,都是内核完成的,所以其是异步。
IO多路转接,优化的是数据等待
阶段,提前将多个文件描述符交给Select/Epoll,他们依次等待多个(将多个文件描述符对应的数据从设备拷贝到内核缓冲区),然后返回一个可读条件,然后交给用户进程进行读取(从内核换从去拷贝到用户缓冲区[指定地址]中)。