使用epoll模型(Linux C++)


代码借鉴于linya大佬的web-server项目:https://github.com/linyacool/WebServer

为什么使用epoll(对比select/poll/epoll)

存储的方式

先介绍一下文件描述符(fd)的概念:在linux系统中,文件至关重要,而进程/线程确定访问文件的方式就是通过一个文件描述符。也可以说文件描述符是内核为管理文件而创建的一个索引。

select存fd的方式是用一个数组,而且一个进程可以监视的最大fd数被限制,一般为1024。这就导致了select在处理百万级并发时捉襟见肘。而且数组的存储形式使得每次检测fd时都要遍历数组,时间复杂度是O(n)级别的。

epoll用一个红黑树的形式(起初用哈希表,但占用空间太大)存fd,而且用一个双链表来保存符合条件的事件,并结合回调机制,这样使得epoll模式索引fd和检测就绪事件的时间复杂度级别到了O(1),也就是epoll模式的效率并不会随着文件的增多而受到影响,使其可以轻松的处理高并发连接的情况。

epoll的两种模式

ET:边沿触发,仅支持no-block socket,即仅有在状态变化的状态接到通知,高效。
LT:水平触发,只要数据没处理就一直通知,是select和poll的工作模式,犯错概率小,但是效率低。

select好于epoll的情况

  1. 并发少,fd不超过1024
  2. 连接都比较活跃,使得O(n)接近于O(1)

代码

头文件

const int MAXEVENTS = 5000;
const int LISTENQ = 1024;

int epoll_init();//初始化一个epoll对象
int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events);//添加一个描述符
int epoll_mod(int epoll_fd, int fd, void *request, __uint32_t events);//修改一个描述符状态
int epoll_del(int epoll_fd, int fd, void *request, __uint32_t events);//删除一个描述符
int my_epoll_wait(int epoll_fd, struct epoll_event *events, int max_events, int timeout);//返回事件数

初始化

int epoll_init()
{
    int epoll_fd = epoll_create(LISTENQ + 1);
    if(epoll_fd == -1)
        return -1;
    //events = (struct epoll_event*)malloc(sizeof(struct epoll_event) * MAXEVENTS);
    events = new epoll_event[MAXEVENTS];
    return epoll_fd;
}

添加fd/修改fd/删除fd

int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events)
{
    struct epoll_event event;
    event.data.ptr = request;//是epoll_data中的一个指针,可以在fd被wait出后用我们自己的函数处理
    event.events = events;
    //printf("add to epoll %d\n", fd);
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event) < 0)
    {//所谓添加/修改/删除,只在epoll_ctl函数的参数有区别,EPOLL_CTL_ADD是添加,ADD换成MOD是修改,换成DEL是删除。
        perror("epoll_add error");
        return -1;
    }
    return 0;
}

返回活跃事件数

int my_epoll_wait(int epoll_fd, struct epoll_event* events, int max_events, int timeout)
{
    int ret_count = epoll_wait(epoll_fd, events, max_events, timeout);
    if (ret_count < 0)
    {
        perror("epoll wait error");
    }
    return ret_count;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值