目录
2.2.3 IO多路复用 (用户不断轮询select/epoll状态,有数据则处理)
2.2.4 异步IO (用户调用后走掉,系统发现数据后通过状态、通知、回调通知调用者)
2)Reactor 模式(通知原来的线程,原来的线程执行处理函数)
3)Proactor 模式 (内核独立线程执行处理函数(回调))
1 操作系统 IO 相关概念
1.1 内核态 / 用户态
为了限制不同的程序之间的访问能力,防止他们获取别的程序的内存数据,或者随意访问外围设备,CPU 为指令划分了访问等级。而在操作系统中,这将分为内核态和用户态两个等级
内核态:CPU可以访问内存所有数据,包括外围设备,例如硬盘,网卡。CPU 也可以将自己从一个程序切换到另一个程序
用户态:只能受限的访问内存,且不允许访问外围设备。占用CPU的能力被剥夺,CPU 可以被抢占
程序从内核态转换为用户态,或从用户态转换为内核态都需要一定的 CPU 资源。
1.2 用户空间、内核空间
同内核态 / 用户态一样,内存虚拟地址空间也被分为两部分,一部分由内核使用,一部分由用户进程使用。
1.3 IO 模型
读操作分为内核准备数据和将数据从内核拷贝到用户空间两个阶段,如图
同样,写操作也分为从用户空间拷贝数据到内核,再从内核写数据到设备两个阶段
2 Linux 系统 I/O 模型
2.1 关于同步,阻塞的解释
陈硕:“
在处理 IO 的时候,阻塞和非阻塞都是同步 IO。
只有使用了特殊的 API 才是异步 IO。
链接:https://www.zhihu.com/question/19732473/answer/26091478
同步和异步:描述的是用户线程与内核的交互方式 (是否有回调?)
- 同步是指用户线程发起 IO 请求后需要等待或者轮询内核 IO 操作完成后才能继续执行;(epoll的epoll_wait())
- 异步是指用户线程发起 IO 请求后仍继续执行自身指令(不等待),当内核 IO 操作完成后会通知用户线程,或者调用用户线程注册的回调函数。---使用异步API, (reactor?)
阻塞和非阻塞:描述的是用户线程调用内核 IO 操作的方式 (read、write?)
- 阻塞是指 IO 操作需要彻底完成后才返回到用户空间。
- 而非阻塞是指 IO 操作被调用后立即返回给用户一个状态值,无需等到 IO 操作彻底完成。(比如调用read读socket的fd,有数据就读取返回读到的数据长度,没数据就返回-1 errno = EAGAIN)
如何区分同步异步、阻塞非阻塞
IO分两阶段(一旦拿到数据后就变成了数据操作,不再是IO):
1.数据准备阶段
2.内核空间复制数据到用户进程缓冲区(用户空间)阶段
(设备)数据准备--->内核copy to 用户空间--->程序
同步 IO 和异步 IO 的区别就在于第二个步骤是否阻塞,如果实际的 IO 读写阻塞请求进程,那么就是同步 IO。(数据从内核拷贝到用户空间过程中,线程是否阻塞?)
阻塞 IO 和非阻塞 IO 的区别在于第一步,发起 IO 请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞 IO,如果不阻塞,那么就是非阻塞 IO。(数据等待的过程中,线程是否等待?)
(阻塞IO和非阻塞IO的区别在于第一步发起IO请求是否会被阻塞:
如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。
一般来讲: 阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。
同步IO和异步IO的区别就在于第二个步骤是否阻塞:
如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO)
更详细:https://www.cnblogs.com/loveer/p/11479249.html