IO多路复用,epoll和select的区别

简介: IO多路复用,epoll和select的区别

IO多路复用

什么是IO多路复用,假设有1000个文件或者网络IO需要我们处理,这里统称为IO,无论IO是否阻塞,总需要有线程去等待IO的完成,那么难道有1000个IO,就要去开1000个线程去监听吗,这样做资源浪费太过严重,所以不同的系统提供了不同的IO多路复用(select,poll,epoll)

I/O 多路复用被用来处理同一个事件循环中的多个 I/O 事件。I/O 多路复用需要使用特定的系统调用,最常见的系统调用是 epoll

epoll

将检测文件描述符的变化委托给内核去处理, 然后内核将发生变化的文件描述符对应的事件返回给应用程序

epoll的底层是红黑树

函数介绍:

int epoll_create(int size)

函数说明: 创建一个树根

参数说明:

  • size: 最大节点数, 此参数在linux 2.6.8已被忽略, 但必须传递一个大于0的数

返回值:

  • 成功: 返回一个大于0的文件描述符, 代表整个树的树根
  • 失败: 返回-1, 并设置errno值

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

函数说明: 将要监听的节点在epoll树上添加, 删除和修改

参数说明:

  • epfd: epoll树根
  • op:

EPOLL_CTL_ADD: 添加事件节点到树上

EPOLL_CTL_DEL: 从树上删除事件节点

EPOLL_CTL_MOD: 修改树上对应的事件节点

  • fd: 事件节点对应的文件描述符
  • event: 要操作的事件节点
struct epoll_event {
  uint32_t     events;      /* Epoll events */
  epoll_data_t data;        /* User data variable */
};
typedef union epoll_data {
  void        *ptr;
  int          fd;
  uint32_t     u32;
  uint64_t     u64;
} epoll_data_t;

event.events常用的有:

  • EPOLLIN: 读事件
  • EPOLLOUT: 写事件
  • EPOLLERR: 错误事件
  • EPOLLET: 边缘触发模式

event.fd: 要监控的事件对应的文件描述符

epoll的两种模式ET和LT模式

  • 水平触发: 只要缓冲区中有数据, 就一直通知
  • 边缘触发: 缓冲区中有数据只会通知一次, 之后再有数据才会通知(若是读数据的时候没有读完, 则剩余的数据不会再通知, 直到有新的数据到来),边缘非阻塞模式: 提高效率

select

多路IO技术: select, 同时监听多个文件描述符, 将监控的操作交给内核去处理,

数据类型

int select(int nfds, fd_set * readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

函数介绍: 委托内核监控该文件描述符对应的读,写或者错误事件的发生

参数说明:

  • fd_set: 文件描述符集合
  • nfds: 最大的文件描述符+1
  • readfds: 读集合, 是一个传入传出参数
    传入: 指的是告诉内核哪些文件描述符需要监控

传出: 指的是内核告诉应用程序哪些文件描述符发生了变化

  • writefds: 写文件描述符集合(传入传出参数)
  • execptfds: 异常文件描述符集合(传入传出参数)
  • timeout:
    NULL–表示永久阻塞, 直到有事件发生
    0 --表示不阻塞, 立刻返回, 不管是否有监控的事件发生
    >0–到指定事件或者有事件发生了就返回

返回值:

  • 成功返回发生变化的文件描述符的个数
  • 失败返回-1, 并设置error值

select优点:

  1. 一个进程可以支持多个客户端
  2. select支持跨平台

select缺点:

  1. 代码编写困难
  2. 会涉及到用户区到内核区的来回拷贝
  3. 当客户端多个连接, 但少数活跃的情况, select效率较低
    例如: 作为极端的一种情况, 3-1023文件描述符全部打开, 但是只有1023有发送数据, select就显得效率低下
  4. 最大支持1024个客户端连接,select最大支持1024个客户端连接不是有文件描述符表最多可以支持1024个文件描述符限制的, 而是由FD_SETSIZE=1024限制的。FD_SETSIZE=1024 fd_set使用了该宏, 当然可以修改内核, 然后再重新编译内核, 一般不建议这么做。

epoll,poll,select总结

select:能够监听的文件描述符最多1024个,实际生产中往往不够用,并且有事件触发了要轮询所有的IO事件,效率低下

poll:本质上和select没什么区别,只是突破了1024这个限制

epoll:没有最大并发连接的限制,而且效率提升,不是轮询的方式,只有有事件发生的event才会返回


目录
相关文章
|
1月前
|
存储 监控 Linux
【Linux IO多路复用 】 Linux下select函数全解析:驾驭I-O复用的高效之道
【Linux IO多路复用 】 Linux下select函数全解析:驾驭I-O复用的高效之道
50 0
|
1月前
|
缓存 Linux API
文件IO和标准IO的区别
文件IO和标准IO的区别
21 2
|
2月前
|
网络协议 安全 测试技术
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
41 2
|
3月前
|
存储 Linux 调度
io复用之epoll核心源码剖析
epoll底层实现中有两个关键的数据结构,一个是eventpoll另一个是epitem,其中eventpoll中有两个成员变量分别是rbr和rdlist,前者指向一颗红黑树的根,后者指向双向链表的头。而epitem则是红黑树节点和双向链表节点的综合体,也就是说epitem即可作为树的节点,又可以作为链表的节点,并且epitem中包含着用户注册的事件。当用户调用epoll_create()时,会创建eventpoll对象(包含一个红黑树和一个双链表);
67 0
io复用之epoll核心源码剖析
|
1月前
|
NoSQL Java Linux
【Linux IO多路复用 】 Linux 网络编程 认知负荷与Epoll:高性能I-O多路复用的实现与优化
【Linux IO多路复用 】 Linux 网络编程 认知负荷与Epoll:高性能I-O多路复用的实现与优化
61 0
|
1月前
|
JavaScript Unix Linux
IO多路复用:提高网络应用性能的利器
IO多路复用:提高网络应用性能的利器
|
3月前
|
消息中间件 架构师 Java
性能媲美epoll的io_uring
性能媲美epoll的io_uring
36 0
|
3月前
|
网络协议 架构师 Linux
一文说透IO多路复用select/poll/epoll
一文说透IO多路复用select/poll/epoll
151 0
|
1月前
|
存储 Java 数据处理
|
1月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同