记录一下io多路复用相关笔记

记录一下io多路复用的相关笔记


什么是io多路复用


  • I/O多路复用(I/O Multiplexing)一种并发编程技术,通过使用某种机制使得程序能够同时监听和处理多个I/O事件允许单个线程处理多个I/O操作,并在有事件就绪时进行相应的操作,而不需要为每个操作创建一个独立的线程
  • 在I/O多路复用中,可以将多个I/O操作添加到一个"多路复用器"中,常见的多路复用器有select poll epoll等。多路复用器会监听I/O操作一旦其中任何一个操作有数据可读、可写或出现异常等就绪事件时,多路复用器将通知程序进行相应的处理
  • 当程序调用多路复用器的等待函数时,它会阻塞在那里,直到任何一个I/O操作有事件就绪。一旦有事件就绪,多路复用器将返回哪些操作就绪以及就绪事件的类型,然后程序就可以根据具体事件类型进行相应的读取、写入或其他操作。
  • I/O多路复用的优势 可以使用更少的线程或进程来处理大量的I/O操作,从而减少了线程切换和资源消耗 相比于传统的一对一的I/O处理方式,它可以提高系统的并发处理能力和资源利用率,特别适用于需要处理大量并发连接或I/O操作的场景,如网络服务器。

总结来说,I/O多路复用是一种通过使用多路复用器来同时管理多个I/O操作的技术,提高程序的并发性和资源利用率。

io多路复用出现的原因和应用场景


I/O多路复用的出现是为了解决传统的一对一的I/O处理方式在大规模并发情况下存在的性能问题。

传统的一对一的I/O处理方式存在以下问题

  • 系统开销大 每个I/O操作都需要创建一个独立的线程或进程来处理,频繁地创建和销毁线程会消耗大量的系统资源,并且切换线程的代价较高。
  • 资源利用率低 由于每个线程或进程只能处理一个I/O操作,在大量并发的情况下,会导致有很多线程或进程处于等待状态,造成资源的低效利用。
  • 扩展性差 当并发量增加时,需要管理的线程或进程数量也呈指数级增长,导致系统无法有效扩展,限制系统的并发能力。

而I/O多路复用机制的优势包括:
  • 资源利用率高 I/O多路复用可以将多个I/O操作集中在一个线程中,并以非阻塞的方式同时监听多个I/O事件。这样可以减少线程或进程的数量,提高系统资源的利用效率。
  • 系统开销低 相比于每个I/O操作都创建一个线程或进程,使用I/O多路复用可以减少创建和销毁线程的开销,降低系统开销。
  • 可扩展性好 使用I/O多路复用可以有效地管理大量并发的I/O操作,使系统能够更好地扩展,处理更多的并发连接。
应用场景:
  • 网络编程 在网络服务器中,常常需要同时监听多个客户端的连接请求,以及处理已连接客户端的读写操作。使用I/O多路复用可以简化服务器编程模型,提高服务器的并发处理能力。
  • 高性能服务器 对于需要处理大量并发连接的高性能服务器,如Web服务器、消息队列服务器等,使用I/O多路复用可以减少线程或进程的数量,提高服务器的性能和扩展性。
  • 异步编程 在异步编程中,使用I/O多路复用可以实现事件驱动的程序设计,通过监听多个I/O事件,以非阻塞的方式处理事件就绪的情况,提高程序的响应速度和并发处理能力。

几种常见I/O多路复用的方式


select


优点


  • 跨平台支持 select 可以在多种操作系统上使用,包括 Windows、Linux 和 macOS 等。
  • 简单易用 select 的接口相对简单,易于理解和使用。
  • 支持大量文件描述符 select 使用位图来表示需要监听的文件描述符集合,理论上可以支持较大数量的文件描述符。

缺点


  • 低效 select 每次调用时需要将所有待监听的文件描述符从用户态拷贝到内核态,这个拷贝操作在文件描述符数量较多时会导致性能下降。
  • 不支持动态增减 一旦设置好了监听的文件描述符集合,就不能动态地增加或删除文件描述符,需要重新设置。
  • 无法知道具体引起事件的文件描述符 当有多个文件描述符就绪时,select 只能返回哪些集合中存在就绪事件,无法直接得知是哪些文件描述符触发了事件。

应用场景


  • 文件传输服务器 当需要同时处理大量客户端请求时,可以使用 select 实现高并发的文件传输服务器。
  • 聊天室或即时通讯应用 通过 select 监听多个客户端的连接和消息读写事件,实现实时的消息传递。

注意事项


  • 文件描述符集合大小限制 不同操作系统对于 select 的文件描述符集合大小有一定限制,需要注意这个限制,避免超出限制导致错误。
  • 阻塞与非阻塞模式 select 适用于同时监听多个文件描述符的读写事件,需要将文件描述符设置为非阻塞模式以避免阻塞整个进程。
  • 避免频繁调用 由于每次调用 select 都要进行拷贝操作,频繁调用 select 可能会导致性能下降,需要合理控制调用频率。

主要步骤或流程


  • 准备文件描述符集合 将所有需要监听的文件描述符添加到 select 的读集合、写集合和异常集合中。
  • 调用 select 等待事件 使用 select 监听文件描述符集合上的事件,当有事件就绪时返回。
  • 处理就绪事件 遍历就绪事件集合,根据事件类型进行相应的处理操作。

poll


优点


  • 跨平台支持 与 select 类似,poll 也可以在多种操作系统上使用。
  • 简单易用 相较于 select,poll 的接口更加简洁,使用起来更加方便。
  • 没有文件描述符数量限制 poll 使用 pollfd 结构体数组来存储待监听的文件描述符和事件类型,没有像 select 那样的位图限制,可以支持较大数量的文件描述符。

缺点


  • 效率不高 与 select 类似,每次调用 poll 也需要将所有待监听的文件描述符从用户态拷贝到内核态,效率较低。
  • 不支持动态增减 与 select 类似,一旦设置好了监听的文件描述符集合,就不能动态地增加或删除文件描述符,需要重新设置。
  • 无法知道具体引起事件的文件描述符 与 select 类似,当有多个文件描述符就绪时,poll 只能返回哪些文件描述符就绪,无法直接得知是哪些文件描述符触发了事件。

应用场景


  • 网络服务器 poll 可以用于实现并发处理多个客户端连接的网络服务器,适用于中小规模的并发需求。
  • 实时数据监控 当需要监听多个实时数据源的变化时,可以使用 poll 来监听这些数据源的事件,并及时处理。

注意事项


  • 文件描述符集合大小限制 不同操作系统对于 poll 的文件描述符集合大小有一定限制,需要注意这个限制,避免超出限制导致错误。
  • 阻塞与非阻塞模式 poll 适用于同时监听多个文件描述符的读写事件,需要将文件描述符设置为非阻塞模式以避免阻塞整个进程。
  • 避免频繁调用 由于每次调用 poll 都要进行拷贝操作,频繁调用 poll 可能会导致性能下降,需要合理控制调用频率。

主要步骤或流程


  • 准备文件描述符集合 将所有需要监听的文件描述符和事件类型添加到 pollfd 结构体数组中。
    调用 poll 等待事件:使用 poll 监听文件描述符集合上的事件,当有事件就绪时返回。
  • 处理就绪事件 遍历就绪事件集合,根据事件类型进行相应的处理操作。

总的来说,poll 是一种简单实用的 I/O 多路复用机制,适用于中小规模的并发场景,如果需要更高的性能和更大规模的并发支持,可以考虑使用更现代的机制如 epoll(Linux)或 kqueue(BSD)。

epoll


优点


  • 高效 epoll 使用事件驱动模型,在等待事件时不需要将所有文件描述符拷贝到内核态,只需将就绪的文件描述符添加到内核事件表中,因此在较大规模并发情况下具有更好的性能。
  • 支持动态增减 epoll 提供了 EPOLL_CTL_ADD、EPOLL_CTL_MOD 和 EPOLL_CTL_DEL 等接口,可以动态地增加或删除需要监听的文件描述符。
  • 有效处理大量文件描述符 epoll 可以应对大数量级的文件描述符,通过使用红黑树或哈希表数据结构,避免了 select 和 poll 中位图的限制。

缺点


  • 仅适用于部分操作系统 epoll 主要用于 Linux 操作系统,无法直接在其他操作系统上使用。
  • 编程模型复杂 与 select 和 poll 相比,epoll 的编程模型稍复杂,需要掌握更多的接口和相关知识。

应用场景


  • 高性能网络服务器 epoll 适用于需要处理大量并发连接的网络服务器,例如 Web 服务器、游戏服务器等。
  • 实时数据处理 当需要实时监测文件、设备或传感器等数据源的变化时,epoll 可以高效处理这些事件。

注意事项


  • 系统资源限制 epoll 需要占用较多的系统资源,包括内存和文件描述符。应注意系统的资源限制,避免超出系统容量。
  • 文件描述符限制 操作系统对于单个进程能打开的文件描述符数量有一定限制,需要根据需求配置适当的文件描述符数量。
  • 边缘触发与水平触发模式 epoll 可以设置为边缘触发(EPOLLET)或水平触发(默认模式),在使用时需要理解两种模式的区别和适用场景。
  • 及时移除不再需要监听的文件描述符 当某个文件描述符不再需要被监听时,应及时从 epoll 中删除,避免资源浪费。

主要步骤或过程


  • 创建 epoll 实例 通过 epoll_create 或 epoll_create1 函数创建一个 epoll 实例。
  • 添加文件描述符 使用 epoll_ctl 函数将需要监听的文件描述符添加到 epoll 实例中。
  • 等待事件 使用 epoll_wait 函数等待事件发生,阻塞直到有事件就绪。
  • 处理就绪事件 遍历就绪事件集合,根据事件类型进行相应的处理操作。

kqueue


优点


  • 高效 kqueue 使用事件驱动模型,可以高效地处理大量并发连接和事件。
  • 简洁高效 相较于 select 和 epoll,kqueue 提供了更简洁、易用的接口,并且具有更好的性能表现。
  • 支持多种事件类型 kqueue 支持多种事件类型,包括读取、写入、错误等,可以满足不同场景下的需求。

缺点


  • 仅适用于 BSD 系统 kqueue 主要用于 BSD 系统(例如 FreeBSD、Mac OS 等),无法直接在其他操作系统上使用。
  • 学习成本较高 kqueue 的编程模型需要理解和掌握,比较复杂,可能对开发人员的学习成本有一定要求。

应用场景


  • 高性能服务器 kqueue 在高性能服务器中广泛应用,特别适合需要高并发和实时事件处理的场景。
  • 文件系统监控 kqueue 可以用于监控文件系统的变化,例如监测文件或目录的创建、修改和删除等事件。
  • 实时通信 kqueue 可以用于实现实时通信的服务器或客户端,例如聊天应用、实时游戏等。

注意事项


  • 文件描述符限制 操作系统对于单个进程能打开的文件描述符数量有一定限制,需要根据需求配置适当的文件描述符数量。
  • 系统资源限制 kqueue 需要占用一定的系统资源,包括内存和文件描述符。应注意系统的资源限制,避免超出系统容量。
  • 注意事件处理顺序 kqueue 返回的就绪事件可能不是按照顺序进行处理的,需要合理设计程序结构,保证正确处理事件。
  • 及时关闭无用文件描述符 当某个文件描述符不再需要被监听时,应及时关闭它,避免资源浪费。

主要步骤或流程


  • 创建 kqueue 实例 使用 kqueue 函数创建一个 kqueue 实例。
  • 添加文件描述符 使用 kevent 函数将需要监听的文件描述符和事件类型添加到 kqueue 实例中。
  • 等待事件 使用 kevent 函数等待事件发生,阻塞直到有事件就绪。
  • 处理就绪事件 遍历就绪事件集合,根据事件类型进行相应的处理操作。

总结


  • select 适用于简单的并发场景,当需要跨平台支持且并发量不是非常高时,可以选择使用 select 来实现I/O多路复用。但在高性能和大规模并发场景下,更加现代化的机制如 epoll 或 kqueue 可能更合适。
  • poll 是一种简单实用的 I/O 多路复用机制,适用于中小规模的并发场景,如果需要更高的性能和更大规模的并发支持,可以考虑使用更现代的机制如 epoll(Linux)或 kqueue(BSD)
  • epoll 是功能强大且高性能的 I/O 多路复用机制,适用于需要处理高并发连接和实时事件的场景。但要注意在使用过程中合理管理资源,并理解边缘触发和水平触发模式的区别
  • kqueue 是在 BSD 系统中使用的高性能 I/O 多路复用机制,适用于需要处理高并发连接和实时事件的场景,尤其是在 BSD 环境下。但要注意系统资源和文件描述符的限制,并理解事件处理的顺序和时机
posted @ 2023-07-07 00:10  Death-Satan  阅读(17)  评论(0编辑  收藏  举报