网络IO模型

同步、异步、阻塞、非阻塞

同步与异步:描述的是用户线程与内核的交互方式,同步指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍然继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

阻塞与非阻塞:描述是用户线程调用内核IO操作的方式,阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

 

阻塞IO(blocking IO)

上述多线程的服务器模型似乎完美的解决了为多个客户机提供问答服务的要求。
但如果要同时响应成百上千路的连接请求,则无论多线程还是多进程都会严重占据系统资源,降低系统对外界响应效率,而线程与进程本身也更容易进入假死状态。

为了上述问题,很多程序员可能会考虑使用“线程池”或“连接池”。减少创建和销毁线程的频率。但所谓“池”始终有其上限,当请求大大超过上限时,“池”构成的系统对外界的响应并不比没有池的时候效果好多少。所以使用“池”必须考虑其面临的响应规模,并根据响应规模调整“池”的大小。对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。

非阻塞IO(non-blocking IO)

在这个方案中recv()更多的是起到检测“操作是否完成”的作用,程序员可能会考虑是不是可以把“所有操作是否完成”的检测放到一个线程或者一个线程池中。

这样子,似乎可以解决上千甚至上万次的客户端请求,导致我们后台线程过多的问题,但循环调用recv()将大幅度推高CPU 占用率。

多路复用IO(IO multiplexing)

在多路复用模型中,是非阻塞,当调用了select和请求数据时也会block,因此是同步类型。
有三种机制实现,select/poll/epoll

Select:《Window Select 源码分享
1.select会使用copy_from_user从用户空间拷贝fd_set到内核空间
2.多次遍历fd_set查看其就绪状态
3.把就绪连接一次性返回。
(与自己写线程,大大减少了调用内核次数)

select的几大缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024

Poll:
poll的实现和select非常相似,只是描述fd集合的方式不同,它没有最大连接数的限制,原因是它是基于链表来存储的

Epoll:


1.开建一个用户内核共享空间
2.把fd维护在一个红黑树中,并对其向设备注测callback事件
3.当fd被设备触发callback从红中节点移至双向链表中
4.遍历双向链表,发现有就绪的就返回

对比:

上面三图分别从 “支持一个进程所能打开的最大连接数”,“FD剧增后带来的IO效率问题”,“消息传递方式”,三方面对比。

  1. 表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。
  2. select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善。

信号驱动IO模型(signal driven IO)

在信号驱动IO中,用户进程会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据
线程请求数据block,因此同步类型。

上述信号驱动IO模型与epoll模型近似,利用了信号驱动更近一步解决FD过大问题

异步IO(Asynchronous I/O)

在异步IO中,当进程发起一个IO操作,进程返回(不阻塞),但也不能返回果结;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据。
是5种IO模型中唯一的异步类型。

与信号驱动IO模型相比,更是近一步减少数据调用环节

IO模型比较

     如图,会发现non-blocking IO和asynchronous IO的区别还是很明显的。在non-blocking IO中,虽然进程大部分时间都不会被block,但是它仍然要求进程去主动的check,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。而asynchronous IO则完全不同。它就像是用户进程将整个IO操作交给了他人(kernel)完成,然后他人做完后发信号通知。在此期间,用户进程不需要去检查IO操作的状态,也不需要主动的去拷贝数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值