BIO到NIO的演化

BIO到NIO的演化
首先明确一点,网络通信最终都是走的操作系统内核,内核的IO功能不断演化,即内核增加增加新的系统调用,使得上层的应用程序能够使用新的系统调用完成更快更好的IO处理。

● BIO时期(阻塞式的IO,因为accept和read都是阻塞的)

  1. 程序想使用操作系统内核完成网络通信的话,如果程序是服务端,服务端启动先调用socket系统调用,得到一个文件描述符,比如3(0 1 2分别是stdin stdout stderr),之后调bind listen accept,等待客户端的连接(accept是阻塞的)。
  2. 如果一个客户端的内核与服务端的内核完成tcp三次握手后,建立起连接,开辟资源。连接的事件给到服务端,accept返回一个新的文件描述符4,代表客户端。
  3. 服务端已经接收了一个连接,接下来想看看这个连接上是不是有数据发过来,可以调用read(4, buf)系统调用,read(fd, buf, count),读的时候有可能读到,也有可能因为客户端没发数据而阻塞。
  4. 假设客户端1是fd4,假设客户端1一直没给服务端发数据,如果此时又有一个客户端2的内核与服务端的内核完成三次握手,建立了tcp连接,那么因为服务端阻塞在read(fd4),则不能给客户端2分配文件描述符。如果客户端有超时逻辑的话,因为服务端一直没响应,过一会客户端会报错。

● BIO时期(多线程对BIO的改善)
可以通过开辟线程来解决上面read阻塞后不能再accept新客户端的问题。服务端的accpt返回fd4之后,可以开辟一个线程,在这个线程A中调用read(fd4),线程A阻塞在read调用上,但是accept就可以接收新的连接了。
弊端:大量客户端连接到服务端时,会创建大量的线程,线程的创建、调度和栈会消耗大量资源。
需要为每个read分配一个线程的本质原因是read和accept时会阻塞。如果能规避掉阻塞这件事情,那么就不需要开辟这么多线程了。

● NIO(将fd配置成非阻塞)
文件描述符可以配置成非阻塞的,意思是read(fd4)时,如果fd4没有发出数据,那么read(fd4)直接抛出一个错误而不是一直阻塞。

弊端:服务端将所有文件描述符报错在内存中,每次循环时需要通过read系统调用读所有的fd,每次系统调用都会有用户态到内核态以及内核态到用户态的切换,引入大量的内核态与用户态相互切换的开销(如果fd的数量的N,则发生N次用户态到内核态的切换以及N次内核态到用户态的切换)。
解决方案:操作系统内核新增select或poll系统调用,服务端只需要保存所有的fd,调用select时传入fd的集合,接下来由内核完成fd的read(时间复杂度是O(N)),这样用户态到内核态的切换次数变成了一次。内核采用轮询的方式处理select(fds),时间复杂度是O(N),内核变量完成后将有数据的结果返回给服务端。

● NIO(引入epoll)
select的弊端:内核采用轮询的方式处理select(fds),时间复杂度是O(N)。

中断机制:
网卡、键盘、摄像头等设备,有数据到达时,会往cpu的总线上发一个中断信号。对于网卡,有数据到达时,网卡会记录数据,计算机内存中开一个buffer(DMA),网卡可以直接把自己收到的数据放入DMA,然后触发一个中断,中断对应一个中断号,中断号在内存中绑定一个回调(驱动做的事情),cpu根据中断号找到回调,回调就可以将已经到达的数据放到一个集合里,返回给服务端。基于中断就会产生事件,从而产生了epoll 。

epoll是个多路复用器,对于每个文件描述符,服务端只需要调用一次epoll_ctl,将fd放入内核中(也就是对于每个客户端,将它的fd通过epoll_ctl放入操作系统的内核中,只要客户端不断开连接,之后通过epoll_wait就可以得到这个客户端所有的事件。每个客户端的fd只会从用户空间向内核空间拷贝一次),这样就规避了调用select时每次将N个fd传入内核中。当客户端传来数据时,产生中断,epoll_wait会返回,服务端就可以读到客户端的数据了。也就是通过epoll可以监听多个文件描述符的事件 。epoll 通过使用红黑树搜索被监控的文件描述符。在 epoll 实例上注册事件时,epoll 会将该事件添加到 epoll 实例的红黑树上并注册一个回调函数,当事件发生时会将事件添加到就绪链表中。epoll的时间复杂度是O(logN)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值