select、poll与epoll

select、poll与epoll

IO多路复用

I/O 多路复用是一种在单个线程或进程中同时监视多个 I/O 操作的机制。通过使用 I/O 多路复用,程序可以等待多个文件描述符(sockets、文件句柄等)中的任何一个变为可读、可写或发生异常,而无需阻塞并等待每个 I/O 操作完成。这使得程序能够更有效地处理并发 I/O 事件,而无需为每个事件创建一个独立的线程或进程。常见的IO多路复用有:select、poll、epoll。

select:简单介绍

(1)简介

select 是一个用于实现 I/O 多路复用的系统调用,通常用于监视多个文件描述符的状态变化。出现的时间比较早

(2)函数原型

#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

(3)参数说明

  • nfds 是待监视的文件描述符中最大的文件描述符加一。
  • readfds、writefds 和 exceptfds 是分别指向可读、可写和异常文件描述符集合的指针。这些集合通过 FD_ZERO、FD_SET、FD_CLR 和 FD_ISSET 等宏来操作。
  • timeout 是超时时间,用于指定 select 调用在等待事件发生的最长时间。如果设置为 NULL,select 将会一直阻塞,直到有事件发生。
  • 返回值:select 返回就绪文件描述符的数量,或者在超时之前无事件发生时返回 0。如果出错,则返回 -1,并设置相应的错误码。

(4)工作原理

调用 select 时,将会阻塞进程,直到监视的文件描述符中的至少一个发生状态变化。
一旦有文件描述符就绪(可读、可写或发生异常),select 将返回,并更新文件描述符集合,以指示哪些文件描述符处于就绪状态。
程序可以使用 FD_ISSET 宏来检查哪些文件描述符已经就绪,并执行相应的 I/O 操作。

(5)底层实现

一般来说Linux内核在实现select时采用的数据结构是位图数组。用于表示文件描述符的状态。

(6)优缺点

  • 优点:select 在许多 UNIX 系统上都有广泛的支持。
    它可以同时监视多种类型的事件(可读、可写、异常等)。
  • 缺点:select 有文件描述符数量的限制,通常在 1024 个左右。每次调用 select 都需要将文件描述符集合从用户空间复制到内核空间,这会带来一定的开销。select 的效率在处理大量文件描述符时可能会下降,因为它采用线性扫描的方式遍历所有的文件描述符。

select:实现echo服务器的并发

select实现echo服务器的并发

poll:简单介绍

(1)简介

与 select 类似,poll 允许程序同时等待多个 I/O 事件的发生,而无需阻塞在单个文件描述符上。

(2)函数原型

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
    int fd;         // 待监视的文件描述符
    short events;   // 关注的事件类型(如 POLLIN、POLLOUT)
    short revents;  // 实际发生的事件类型
};

(3)参数说明

  • fds: 是一个指向 struct pollfd 数组的指针,每个 struct pollfd 结构体用于描述一个待监视的文件描述符及其关注的事件。
  • nfds: 是 fds 数组的长度,即待监视的文件描述符的数量。
  • timeout: 是超时时间,用于指定 poll 调用在等待事件发生的最长时间。如果设置为负数,poll 将会一直阻塞,直到有事件发生。如果设置为 0,poll 将会立即返回,不等待事件发生。
  • poll 返回就绪文件描述符的数量,或者在超时之前无事件发生时返回 0。如果出错,则返回 -1,并设置相应的错误码。

(4)工作原理

  • 调用 poll 时,程序会阻塞在此处,等待监视的文件描述符中的任何一个发生状态变化。
  • 一旦有文件描述符就绪,poll 将返回,并更新 revents 字段,以指示文件描述符的就绪状态。
  • 程序可以检查 revents 字段来确定哪些文件描述符已经就绪,并执行相应的 I/O 操作。

(5)底层实现

linux中,poll使用了poll_table来管理文件描述符集合,通常是
为了快速查找和管理文件描述符及其对应的事件,底层数据结构一般会采用哈希表或者红黑树。

(6)优缺点

  • 优点:poll 没有文件描述符数量的限制,适用于大规模的并发连接。
    它的使用比 select 更简单,因为不需要设置文件描述符的最大值。
  • 缺点:每次调用 poll 都需要将文件描述符集合从用户空间复制到内核空间,这可能会产生一定的开销。在处理大量文件描述符时,效率可能不如 epoll。

poll:实现echo服务器的并发

poll实现echo服务器的并发

epoll:简单介绍

(1)简介

epoll与传统的 select 和 poll 相比,epoll 在处理大量并发连接时具有更好的性能表现。主要原因就是采用了内存映射技术、边缘触发模式、可扩展性强。

(2)函数原型

#include <sys/epoll.h>
//创建epoll实例
int epoll_create(int size);
//修改epoll实例属性
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
//等待事件发生
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
//相关结构体
struct epoll_event {
    uint32_t events;  // 表示感兴趣的事件类型,可以是 EPOLLIN、EPOLLOUT、EPOLLERR 等。
    epoll_data_t data;  // 包含事件相关的数据,可以是文件描述符或者指针。
};

(3)工作原理

  • 创建 epoll 实例:使用 epoll_create 系统调用创建一个 epoll 实例,返回一个文件描述符,该文件描述符代表了这个 epoll 实例。
  • 注册文件描述符:使用 epoll_ctl 系统调用向 epoll 实例注册文件描述符,并设置关注的事件类型(如可读、可写、异常等)。也可以通过 EPOLL_CTL_ADD、EPOLL_CTL_MOD 和 EPOLL_CTL_DEL 操作来添加、修改和删除文件描述符。
  • 等待事件发生:使用 epoll_wait 系统调用等待事件发生。
    内核会检查注册的文件描述符,如果有文件描述符上发生了关注的事件,则将这些事件返回给用户空间。
  • 处理事件:用户程序接收到事件后,可以根据事件类型进行相应的处理。可以使用 epoll_data 结构体的 ptr 字段来存储用户定义的数据,以便在事件发生时进行回调操作。

(4)触发模式

  • 水平触发模式(LT):此模式下,发生事件若未及时处理,会一直处于就绪状态,直到处理该事件。每次调用wait时都会被返回为就绪状态
  • 边缘触发模式(ET):此模式下,发生事件若未及时处理,下次调用wait时,不会返回就绪状态,除非有新的事件发生。

(5)内存映射技术

所谓内存映射技术就是直接将事件表映射到用户空间(用户态)避免内核态与用户态之间切换的开销。减少系统调用次数和数据拷贝次数。

epoll:实现echo服务器的并发

epoll实现echo服务器的并发

  • 61
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值