1. I/O的四种模型的概念
I/O操作 主要分成两部分
① 数据准备,将数据加载到内核缓存
② 将内核缓存中的数据加载到用户缓存
1.1 Synchronous blocking I/O——同步阻塞I/O
数据拷贝指请求到的数据先存放在内核空间, 然后从内核空间拷贝至程序的缓冲区
-
Typical flow of the synchronous blocking I/O model
1.2 Synchronous non-blocking I/0——同步非阻塞I/O
用户线程不断发起IO请求. 数据未到达时系统返回一状态值; 数据到达后才真正读取数据
-
Typical flow of the synchronous non-blocking I/O model
1.3 Asynchronous blocking I/0——异步阻塞I/O
IO多路复用建立在内核提供的阻塞函数select上。
用户先将需要进行IO操作的socket添加到select中,然后等待阻塞函数select返回。当数据到达后,socket被激活,select返回,用户线程就能接着发起read请求
-
Typical flow of the asynchronous blocking I/O model (select)
1.4 Asynchronous non-blocking I/0——异步非阻塞I/O
-
Typical flow of the asynchronous non-blocking I/O model
我们可以给select注册多个socket, 然后不断调用select读取被激活的socket,实现在同一线程内同时处理多个IO请求的效果.
更进一步, 我们把select轮询抽出来放在一个线程里, 用户线程向其注册相关socket或IO请求,等到数据到达时通知用户线程,则可以提高用户线程的CPU利用率.
2. 同步和异步的区别
堵塞、非堵塞的区别是在于第一阶段,即数据准备阶段。无论是堵塞还是非堵塞,都是用应用主动找内核要数据,而read数据的过程是‘堵塞’的,直到数据读取完。
同步、异步的区别在于第二阶段,若由请求者主动的去获取数据,则为同步操作,需要说明的是:read/write操作也是‘堵塞’的,直到数据读取完。
若数据的read都由kernel内核完成了(在内核read数据的过程中,应用进程依旧可以执行其他的任务),这就是异步操作。
3. I/O多路复用
概述:
I/O多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。
后面将继续介绍:
1)select和Epoll的区别
2)windows消息循环机制
3)Reactor设计模式
4)一个使用Reactor模式+线程池的具体实例——muduo库Eventloop(事件循环)的设计