Unix网络编程中的五种IO模型
- Blocking IO - 阻塞IO
- NoneBlocking IO - 非阻塞IO
- IO multiplexing - IO多路复用
- signal driven IO - 信号驱动IO
- asynchronous IO - 异步IO
重点介绍一下IO多路复用:
IO多路复用是阻塞的,只是它是被select函数阻塞,而不是被系统调用阻塞。
select里面不断轮询每个IO,有IO的数据准备好了,它就把数据接收过来,然后又进到select去轮询…
直到全部数据都被接收。
摘录地址:https://www.jianshu.com/p/b8203d46895c
I/O System Call 的阻塞/非阻塞,同步/异步
-
阻塞和非阻塞
阻塞和非阻塞描述的是进程的一个操作是否会使得进程转变为“等待”的状态,关注程序在等待调用结果(消息,返回值)时的状态。 -
同步和异步
同步和异步关注的是消息通信机制。
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。
摘录地址:https://www.zhihu.com/question/19732473/answer/241673170
非阻塞I/O系统调用和异步I/O系统调用的区别
非阻塞I/O 系统调用( nonblocking system call ) 和 异步I/O系统调用 (asychronous system call)的区别:
- 一个非阻塞I/O 系统调用 read() 操作立即返回的是任何可以立即拿到的数据,可以是完整的结果,也可以是不完整的结果,还可以是一个空值。
- 而异步I/O系统调用 read()结果必须是完整的,但是这个操作完成的通知可以延迟到将来的一个时间点。
IO多路复用的三种机制select,poll,epoll
1.select
1)使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差.但在一个线程内同时处理多个socket的IO请求。
2)每次调用select,都需要把fd_set集合从用户态拷贝到内核态,如果fd_set集合很大时,那这个开销也很大
3)每次调用select都需要在内核遍历传递进来的所有fd_set,如果fd_set集合很大时,那这个开销也很大
4)为了减少数据拷贝带来的性能损坏,内核对被监控的fd_set集合大小做了限制,并且这个是通过宏控制的,大小不可改变(限制为1024)
2.poll
poll只解决了上面的问题4,并没有解决问题2,3的性能开销问题。
3.epoll
1)基于事件驱动的I/O方式
2)epoll没有描述符个数限制,使用一个文件描述符管理多个描述符
3)将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次
水平触发和边缘触发的区别
水平触发(LT):默认工作模式,即当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序可以不立即处理该事件;下次调用epoll_wait时,会再次通知此事件
边缘触发(ET): 当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次通知此事件。(直到你做了某些操作导致该描述符变成未就绪状态了,也就是说边缘触发只在状态由未就绪变为就绪时只通知一次)。
参考链接:
1.https://www.jianshu.com/p/397449cadc9a
2.https://blog.csdn.net/daaikuaichuan/article/details/83862311
3.https://leetcode-cn.com/circle/discuss/uHGOZo/