linux内核视角看epoll

本文介绍了Linux中epoll多路复用技术如何在一个线程中同时处理多个Socket连接,通过epoll_create、epoll_ctl和epoll_wait实现高并发和资源效率。同时,对比了JavaNIO的事件轮询机制,强调了epoll在大量连接场景下的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

在传统的阻塞I/O模型中,一个Socket(套接字)通常只能处理一个TCP连接,即一对一的关系。每个TCP连接都需要分配一个独立的Socket来处理。
然而,使用多路复用技术,可以在单个线程中同时监视多个Socket的状态,以确定哪些Socket有可读或可写事件。通过在单个线程内等待和处理多个连接的事件,高效地处理大量的并发连接,减少资源消耗。

二、epoll

在linux上多路复用技术有select、poll、epoll。其中epoll的性能表现是最优异的,能支持的并发量也最大。linux中和epoll相关的函数有如下三个:

  1. epoll_create: 创建一个epoll对象。
  2. epoll_ctl: 向epoll对象添加要管理的连接。
  3. epoll_wait: 等待epoll对象管理的连接上的IO事件。

三、epoll内核对象的创建

用户进程调用epoll_create时,内核会创建一个eventpoll的内核对象,并把它加入到当前进程已打开的文件列表中。eventpoll内核对象的定义如下:,

struct eventpoll {
   
    //等待队列
    wait_queue_head_t wq;
    //就绪的描述符链表
    struct list_head rdllist;
    //每个eventpoll对象中都有一颗红黑树
    struct rb_root rbr;
}
  • wq:等待队列。用户进程陷入阻塞时,其进程描述符会保存在eventpoll对象的等待队列。
  • rbr:一颗红黑树。用来管理用户进程添加进来的所有的socket,为了支持对海量连接的高效查找、插入和删除。
  • rdllist:就绪的描述符链表。当有连接事件就绪的时候,内核会把就绪的连接放到rdllist,这样只需要判断rdllist链表就能找出就绪的连接,而不用去遍历整颗树

四、epoll添加socket

这一步是由用户进程调用epoll_ctl完成的。假设现在和客户端的多个连接的socket都创建好了,也创建好了eventpoll对象。epoll_ctl在注册每一个socket的时候,内核都会做如下三件事情:

  1. 初始化一个红黑树节点对象epitem。
  2. 在socket对象的等待队列中,注册事件到达回调函数ep_poll_callback
  3. 将epitem插入eventpoll的红黑树。
struct epitem {
   
    ......
    struct epoll_filefd ffd; //socket句柄
	struct eventpoll *ep; //所属的eventpoll
}

通过epoll_ctl添加两个socke以后,这些内核数据结构最终在进程中的关系如下:
在这里插入图片描述

4.1 设置socket对象等待队列

epoll_ctl先完成epitem对象的初始化后,接着就会去设置socket的等待队列,把ep_poll_callback设置为socket数据就绪时的回调函数,注册到socket等待队列

// include/linux/wait.h
static inline void init_waitqueue_func_entry(wait_queue_t *q
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值