epoll多路复用

目录

1. epoll的接口使用

1.1 创建

1.2 监听队列

1.3 就绪队列

2. epoll的底层实现

3. epoll VS select

3.1 select的缺点

3.2 epoll的优点

4. epoll对文件描述符操作的两种模式

4.1 概念

4.2 为什么ET模式又称为高效模式?

4.3 ET模式下需要注意什么?

4.4 两种实现方式


1. epoll的接口使用

1.1 创建

//创建
int epoll_create(int size);
//size无实际意义,默认填大于0的数
//返回非负文件描述符

1.2 监听队列

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
//epfd: epoll_create的返回值
//op: EPOLL_CTL_ADD | EPOLL_CTL_MOD | EPOLL_CTL_DEL
//event: 结构体
    struct epoll_event {
        uint32_t events; /* Epoll events */
        epoll_data_t data; /* User data variable */
    };
    typedef union epoll_data {
        void *ptr;
        int fd;
        uint32_t u32;
        uint64_t u64;
    } epoll_data_t;

1.3 就绪队列

//等待
int epoll_wait(int epfd, struct epoll_event *events, 
               int maxevents, int timeout);

2. epoll的底层实现

① 调用epoll_create

     用户空间返回一个epfd,内核此时创建一个event结构体,其中有两个重要成员:红黑树和双向链表。红黑树保存需要监听的文件描述符;双向链表保存就绪的文件描述符。

② 调用epoll_ctl

     操作的是红黑树

③ 调用epoll_wait

     操作的是双向链表

3. epoll VS select

3.1 select的缺点

① select监控的文件描述符有限,最多1024个;

② select需要将监听的文件描述符加入到监听队列,将数据从用户态拷贝到内核态,浪费时间;

③ select监控就绪的文件描述符时需要轮询位图,浪费时间;

④ select需要将就绪的文件描述符从内核态拷贝到用户态,浪费时间。

3.2 epoll的优点

① 监视的文件描述符数量只与内存大小有关,epoll对其不做限制;

② epoll将文件描述符一次性加入到红黑树中,永久有效,即“一次注册,永久生效”。

     将文件描述符加入到红黑树的同时,内核会给每一个文件描述符注册一个回调函数,当文件描述符就绪时,会主动调用回调函数将自己添加到双向链表。

NOTICE:当监控的文件描述符数量很少时,select比epoll的平均响应时间更低。

4. epoll对文件描述符操作的两种模式

4.1 概念

LT (Level_trigger): 水平触发  当被监控的文件描述符上有可读写事件发生时,epoll_wait会通知处理程序去读写,如果这次没有把数据一次性全部读写完,那下次调用epoll_wait时,它还会在上次没读写完的文件描述符上继续读写

ET (Edge_trigger): 边缘触发  当被监控的文件描述符上有可读写事件发生时,epoll_wait会通知处理程序去读写,如果这次没有把数据一次性全部读写完,那下次调用epoll_wait时,它不会通知你,直到文件描述符上出现第二次读写事件才会通知

4.2 为什么ET模式又称为高效模式?

        ET模式很大程度上减少了epoll事件被重复触发的次数(ET模式下执行一次epoll_wait系统调用,LT模式下需要多次执行)

4.3 ET模式下需要注意什么?

        ET模式下必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作导致处理多个文件描述符的任务饥饿。

4.4 两种实现方式

① recv设置为非阻塞

ret = recv(newFd, buf, sizeof(buf), MSG_DONTWAIT);

② 将文件描述符设为非阻塞

void setNonBlock(int fd){
    int status = 0;
    //获取fd的状态
    status = fcntl(fd, F_GETFL);
    //设为为非阻塞态
    status |= O_NONBLOCK;
    fcntl(fd, F_SETFL, status);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值