io多路复用

118 阅读2分钟
  • 当计算机在切换用户态,内核态时,他们是如何通知彼此有事件发生的呢;
  • 其实有bio,nio,aio IO的通信,是这里面有很多阻塞,我们只能够通过多个线程来避免主线程的阻塞。

bio

如果有大量的连接过来,那服务器需要创建很多个线程与之对应,并且线程的创建也是需要消耗资源的,因为线程使用的栈是独占的(栈大小默认1MB),同时CPU的资源调度也是需要浪费。

nio

NIO可让您只使用一个(或几个)单线程管理多个通道(网络连接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂

aio

主要是包含io多路复用,有select,poll,epoll方式。

select 实现多路复用的方式是,

1、将已连接的 Socket 都放到一个文件描述符集合,

2、然后调用 select 函数将文件描述符集合拷贝到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此 Socket 标记为可读或可写,

3、接着再把整个文件描述符集合拷贝回用户态里,然后用户态还需要再通过遍历的方法找到可读或可写的 Socket,然后再对其处理。

poll 不再用 BitsMap 来存储所关注的文件描述符,取而代之用动态数组,以链表形式来组织,突破了 select 的文件描述符个数限制,当然还会受到系统文件描述符限制

epoll 通过两个方面,很好解决了 select/poll 的问题。

epoll 使用事件驱动的机制,内核里维护了一个链表来记录就绪事件,当某个 socket 有事件发生时,通过回调函数内核会将其加入到这个就绪事件列表中,当用户调用 epoll_wait() 函数时,只会返回有事件发生的文件描述符的个数,不需要像 select/poll 那样轮询扫描整个 socket 集合,大大提高了检测的效率。