type
status
date
slug
summary
tags
category
icon
password
创建时间
Oct 31, 2024 01:59 PM
socket的多路复用,指的是在单个线程或进程中可以同时处理多个socket的 I/O 事件,可以提高整体效率和资源利用率。
常见的多路复用机制包括 select、poll 和 epoll,在Linux平台上这种机制主要依赖于epoll,因为它在大多数情况下性能更好。epoll是Linux内核针对大量并发连接进行高效管理的系统调用接口。
编程过程中,建议使用 epoll。epoll 相比于 select 和 poll,主要有以下几个优点:
- 效率高: epoll 使用事件通知的方式能够解决轮询(polling)带来的性能瓶颈,对大量文件描述符的处理效率高。
- 不受描述符数量限制:
select
有文件描述符数量的上限(通常是1024),而 epoll没有这种限制。 - 数据结构设计:select 使用一个固定大小的位图(
bitmap
)来表示文件描述符集。在大多数实现中,这个位图的大小是由FD_SETSIZE
常量定义的,默认值通常为 1024。这意味着最多只能监控 1024 个文件描述符。 - 效率考虑:随着监控的文件描述符数量增加,遍历和更新这些位图所需的时间也会增加。因此,为了保持较好的性能表现,选择了一个相对合理且常见使用场景下足够大的默认值。
- 历史原因:早期 UNIX 系统资源有限,而网络应用程序规模相对较小,因此设置这样的默认限制可以满足当时的大部分需求,并减少不必要的复杂性。
为什么select 系统调用在许多操作系统中确实有文件描述符数量的上限?这个限制主要源于以下几个原因:
- 内存拷贝少: epol l的系统调用仅在需要数据时进行内存拷贝,减少了系统开销。
- 支持边沿触发:相比于select和poll的水平触发(level-triggered), epoll 还支持边沿触发(edge- triggered),能够适应更多的应用场景。
扩展
可以从几个方面进一步展开:
select
和poll
的缺点:select
和poll
都是 I/0 多路复用的早期实现,但它们有一些不足。例如,select
在每次调用时都需要重新传递所有文件描述符集合,并进行内存拷贝,而poll
则需要传递整个文件描述符数组,这在文件描述符特别多的情况下,性能开销很大。此外,select
还有一个描述符数量的限制。
- epoll的工作机制: epoll使用两个系统调用来操作:
epoll_create
创建一个epoll实例,epoll_ctl
增加、修改或删除要控制的文件描述符。epoll_wait
则是用于等待事件的发生。与select
不同的是,epoll
每次只需传递发生的事件,不需要传递所有文件描述符,极大提高了效率。
- 边沿触发与水平触发:水平触发(Level-triggered, LT)是默认的触发模式,处理器只要发现事件有未处理的数据就会再次通知,在传统的select 和 poll中也是这种方式。而边沿触发(Edge-triggered, ET)是更高效的一种方式,它只会在状态变化(例如从无数据到有数据)时通知一次,开发难度稍大但可以减少系统调用次数,提高性能。