面试题答案
一键面试select
- 工作原理:
select
函数监控一组文件描述符(fd_set
),包括读、写和异常事件。- 应用程序将需要监控的文件描述符集合传递给
select
函数。 select
函数阻塞等待,直到集合中的某个文件描述符有事件发生(可读、可写或异常),或者超时。- 函数返回后,应用程序需要遍历整个文件描述符集合,以确定哪些文件描述符上发生了事件。
- 优点:
- 跨平台支持好,几乎所有操作系统都支持。
- 简单易用,对于小规模的应用开发较为方便。
- 缺点:
- 单个进程能够监控的文件描述符数量有限,通常在1024左右(可通过修改系统参数提高,但仍有上限)。
- 每次调用
select
都需要将文件描述符集合从用户态拷贝到内核态,开销较大。 - 线性扫描文件描述符集合来确定就绪的描述符,时间复杂度为 O(n),当文件描述符数量较多时效率较低。
poll
- 工作原理:
poll
函数和select
类似,也是用于监控文件描述符的事件。- 它使用一个
pollfd
结构体数组来表示需要监控的文件描述符集合及其感兴趣的事件。 poll
函数同样阻塞等待,直到数组中的某个文件描述符有事件发生,或者超时。- 返回后,应用程序同样需要遍历数组来找出就绪的文件描述符。
- 优点:
- 没有文件描述符数量的限制(理论上只受限于系统资源)。
- 相比
select
,poll
传递参数的方式更灵活,结构体数组的形式比fd_set
更直观。
- 缺点:
- 每次调用仍需将数据从用户态拷贝到内核态,开销依然存在。
- 查找就绪文件描述符的方式依然是线性遍历,时间复杂度为 O(n),在文件描述符较多时性能较差。
epoll
- 工作原理:
- epoll_create:首先通过
epoll_create
创建一个 epoll 实例,内核会为该实例分配一个内核对象,用于管理需要监控的文件描述符。 - epoll_ctl:通过
epoll_ctl
函数向这个 epoll 实例中添加、修改或删除需要监控的文件描述符及其感兴趣的事件。内核会在内核空间中构建一棵红黑树来存储这些文件描述符,这样添加、删除操作的时间复杂度为 O(logn)。 - epoll_wait:调用
epoll_wait
函数阻塞等待事件发生。当有事件发生时,内核会将就绪的文件描述符放入一个就绪链表中。epoll_wait
返回时,直接将这个就绪链表传递给用户态,应用程序只需遍历这个链表就可以获取所有就绪的文件描述符,时间复杂度为 O(1)。
- epoll_create:首先通过
- 优点:
- 支持大量的文件描述符,能轻松处理数以万计的文件描述符。
- 事件驱动机制,只有发生事件的文件描述符才会被通知,减少了无效的遍历。
- 内核和用户空间数据拷贝开销小,通过共享内存方式传递就绪列表。
- 缺点:
- 只在 Linux 系统上支持,跨平台性不如
select
。 - 接口相对复杂,使用起来需要一定的学习成本。
- 只在 Linux 系统上支持,跨平台性不如