简单通俗理解IO多路复用原理

核心技术

  • 一个线程处理多个 I/O 连接
  • 非阻塞式处理
  • 基于事件驱动

1. 文件描述符与就绪状态

在 Linux 系统中,每个网络连接都被抽象为一个文件描述符(fd)。一个文件描述符可能处于以下几种状态:

// 可能的事件状态
#define EPOLLIN     0x001    // 可读
#define EPOLLOUT    0x004    // 可写
#define EPOLLERR    0x008    // 错误
#define EPOLLHUP    0x010    // 连接断开

2. 数据就绪的判定

以 TCP 连接为例,"有数据可读"的具体情况包括:

  1. Socket 缓冲区
struct sock_buff {
    char* buffer;      // 数据缓冲区
    size_t data_len;   // 当前数据长度
    size_t capacity;   // 缓冲区容量
};

当以下任一情况发生时,系统会标记该 fd 为"可读":

  • 接收缓冲区中有新数据到达
  • 对端关闭连接(收到 FIN 包)
  • 有新的连接到达(对于监听 socket)

3. 内核通知机制

以 epoll 为例,其工作流程:

// 1. 创建 epoll 实例
int epfd = epoll_create(1);

// 2. 注册感兴趣的 fd
struct epoll_event event;
event.events = EPOLLIN;  // 监听读事件
event.data.fd = client_fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &event);

// 3. 等待事件发生
struct epoll_event events[MAX_EVENTS];
while (1) {
    // 阻塞等待事件
    int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);

    // 处理就绪的事件
    for (int i = 0; i < nfds; i++) {
        if (events[i].events & EPOLLIN) {
            // 有数据可读
            handle_read(events[i].data.fd);
        }
    }
}

4. 实际工作流程

让我们看一个具体的例子:

  1. 初始状态
客户端 A、B、C 都已连接到服务器
- A 的 fd = 3
- B 的 fd = 4
- C 的 fd = 5
所有连接都在 epoll 实例中注册

  1. 数据到达过程
时刻 1: 所有连接都没有数据
epoll_wait() -> 阻塞等待

时刻 2: 客户端 B 发送数据
- 数据到达内核缓冲区
- 内核标记 fd 4 为可读
- epoll_wait() 返回,events 数组包含 fd 4

时刻 3: 处理 fd 4 的数据
- 读取数据
- 处理完成后继续 epoll_wait()

5. 性能优势

假设有 1000 个连接,但只有 2 个连接有数据:

传统轮询方式:
- 需要遍历 1000 次
- 998 次检查都是无效的

epoll 方式:
- epoll_wait 直接返回 2
- 只需处理 2 个有数据的连接
- 避免了 998 次无效的系统调用

6. 内存影响

// 每个连接的数据结构
struct connection {
    int fd;
    void *buffer;
    size_t buffer_size;
};

// 传统方式
struct connection conns[MAX_CONNECTIONS];  // 所有连接都需要分配资源

// epoll 方式
struct epoll_event events[MAX_EVENTS];     // 只需要处理活跃连接

这种机制使得系统资源使用更加高效,特别是在大量连接但活跃连接较少的场景下(这正是 Redis 的典型使用场景)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值