举例一.同步阻塞IO服务端一直循环等待连接每次循环只处理一个请求。会在accept和read方法进行阻塞多线程时需要创建对应的线程数去操作二.同步非阻塞accept不阻塞如果没有连接返回一个非法的值一直循环如果有连接就加到fd_list中缺点需要一直循环三 .select模式下面是大概的源码。1.重置FD_SET是bitmap 默认只有1024位2.for循环把初始化拿到的fds[i]跟rset绑定。需要监听哪几位fd3.调用select方法从用户态拷贝fd到内核态。会进行遍历fd。查看有没有哪个fd就绪了返回总共就绪的数量int如果一直没有则阻塞4.由于只是返回了就绪个数不知道哪个就绪了所以还需要一次遍历来确定就绪的fd然后调用read来读数据fd_set 入参表示要监听哪些fd如图1号和3号需要监听出差表示哪些FD就绪如图3号准备好了缺点1FD_SET是bitmap 默认只有1024位所以默认监听1024fd2处理完一轮后需要重新初始化FD_SETFD_SET不能复用3每次调用select需要把fd从用户态拷贝到内核态调用完成后还要把全部fd从内核态拷贝到用户态占用内存4需要遍历全部的fd来找到就绪的fd来执行逻辑需要On复杂度四 .poll模式源码大致如下。pollfds结构中fd表示监听的文件描述符events表示监听的事件,revents表示就绪的事件。poll方法入参文件描述符数组数组长度超时时间出参就绪的个数跟select类似将一批fd发送到内核态进行判断。就绪了就返回同时把对应的revents设置为1因为也不知道哪个fd就绪了还是需要全部遍历但是在遍历的过程中就把revents设置为0统一做一次初始化。使用的pollfds数据结构组成数组没有1024的限制五.epoll模型创建实例epoll_create1() 分配 struct eventpoll初始化红黑树 rbr 就绪链表 rdllist注册监听epoll_ctl(EPOLL_CTL_ADD) 创建 struct epitem插入红黑树 rbr注册回调 ep_poll_callback 到 fd 的等待队列等待事件epoll_wait()检查就绪链表 rdllist 是否为空空则进入睡眠 (TASK_INTERRUPTIBLE)事件到达文件就绪驱动调用 wake_up() 唤醒等待队列触发 ep_poll_callback 回调将 epitem 加入就绪链表 rdllist唤醒 epoll_wait 中的进程返回事件epoll_wait 被唤醒遍历就绪链表 rdllist拷贝事件到用户空间 events 数组返回就绪事件数量两种模式LT vs ET 对比。默认LT六.对比参考链接https://www.bilibili.com/video/BV1r54y1f7bU/?spm_id_from333.337.search-card.all.clickvd_sourced9a52d82a1f11ceeeb7021c93269e8d2https://www.bilibili.com/video/BV1gN411e7gd/?spm_id_from333.337.search-card.all.clickvd_sourced9a52d82a1f11ceeeb7021c93269e8d2