Netty——(3)高并发编程必备知识IO多路复用技术select、poll、epoll分析

目录

 

1.什么是IO多路复用:

2.select基本原理:

3.poll的基本原理:

4.epoll基本原理:

5.三种模型之间的比较


 1.什么是IO多路复用:

    I/O多路复用,I/O是指网络I/O, 多路指多个TCP连接(即socket或者channel),复用指复用一个或几个线程

    简单来说:就是使用一个或者几个线程处理多个TCP连接

    最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程

2.select基本原理:

        监视文件3类描述符: writefds、readfds、和exceptfds       (Linux一切即文件)

Netty——(3)高并发编程必备知识IO多路复用技术select、poll、epoll分析

    调用后select函数会阻塞住,等有数据 可读、可写、出异常 或者 超时 就会返回

select函数正常返回后,通过遍历fdset整个数组才能发现哪些句柄发生了事件,来找到就绪的描述符fd,然后进行对应的IO操作

几乎在所有的平台上支持,跨平台支持性好

select一般支持几千上万个连接

缺点:

         1)select采用轮询的方式扫描文件描述符,全部扫描,随着文件描述符FD数量增多而性能下降               

         2)每次调用 select(),需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)

         3)最大的缺陷就是单个进程打开的FD有限制,默认是1024   (可修改宏定义常量,但是效率仍然慢)

         单个进程不可能一下打开几百万个连接

         static final  int MAX_FD = 1024   即使修改由于上面两个问题也不会支持百万级别的连接

3.poll的基本原理:

select() 和 poll() 系统调用的大体一样,处理多个描述符也是使用轮询的方式,根据描述符的状态进行处理

一样需要把 fd 集合从用户态拷贝到内核态,并进行遍历。

最大区别是: poll没有最大文件描述符限制(使用链表的方式存储fd)

单项链表双向链表可以无限的拓展

支持几千上万连接

4.epoll基本原理:

在2.6内核中提出的,对比select和poll,epoll更加灵活,没有描述符限制,用户态拷贝到内核态只需要一次

使用事件通知,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用callback的回调机制来**对应的fd(洗衣服的例子)

 

    优点:

    1)没fd这个限制,所支持的FD上限是操作系统的最大文件句柄数(Linux的最大的句柄数可以查看一般65535  但是可以进行调整的可以调成几十W),1G内存大概支持10万个句柄(16G内存单机支持百万的连接也是可以的只要模型使用的正确

    2)效率提高,使用回调通知而不是轮询的方式,不会随着FD数目的增加效率下降

    3)通过callback机制通知,内核和用户空间mmap同一块内存实现(不需要copy来copy去

 Linux内核核心函数(c里面的)(select和poll只有一个函数select/poll)

epoll中一组函数通过这三个函数之间的配合完成处理百万级别的连接

1)epoll_create()  在Linux内核里面申请一个文件系统 B+树,返回epoll对象,也是一个fd

2)epoll_ctl()   操作epoll对象,在这个对象里面修改添加删除对应的链接fd, 绑定一个callback函数

如epoll对象中有100万个连接,--->其中活跃的有1万   ---->把这10000个活跃的fd放到一个集合epoll_wait

只需判断集合是否为空把所有的fd进行IO操作就好了    根本不需要进行轮询

3)epoll_wait()  判断并完成对应的IO操作

缺点:

     编程模型比select/poll 复杂

     例子:100万个连接,里面有1万个连接是活跃,在 select、poll、epoll分别是怎样的表现

     select:不修改宏定义,则需要 1000个进程才可以支持 100万连接

     poll:100万个链接,遍历都响应不过来了,还有空间的拷贝消耗大量的资源

     epoll: 不需轮询 不需copy (三个函数巧妙的配合就能完成单机支持百万的连接)

5.三种模型之间的比较

Netty——(3)高并发编程必备知识IO多路复用技术select、poll、epoll分析