Linux面试必知: 一句话讲透epoll

本文聚焦Linux中的epoll,介绍其是一种I/O事件通知机制,基于文件描述符,当内核读或写缓冲区满足条件时发出相应信号。还阐述了水平触发和边缘触发的区别,最后介绍了epoll的三个接口,包括创建实例、操作监控事件和等待事件触发。

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

Linux面试必知: 一句话讲透epoll
epoll概念

在Linux的Man文档中,我们可以看到如下定义

    Epoll - I/O event notification facility

翻译一下,epoll是一种I/O事件通知机制,这句话基本上包含了所有需要理解的要点

    I/O事件
        基于file descriptor,支持file, socket, pipe等各种I/O方式
        当文件描述符关联的内核读缓冲区可读,则触发可读事件,什么是可读呢?就是内核缓冲区非空,有数据可以读取
        当文件描述符关联的内核写缓冲区可写,则触发可写事件,什么是可写呢?就是内核缓冲区不满,有空闲空间可以写入
    通知机制
        通知机制,就是当事件发生的时候,去通知他
        通知机制的反面,就是轮询机制

以上两点结合起来理解

    epoll是一种当文件描述符的内核缓冲区非空的时候,发出可读信号进行通知,当写缓冲区不满的时候,发出可写信号通知的机制

水平触发与边缘触发

    水平触发(level-trggered)
        只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
        当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
    边缘触发(edge-triggered)
        当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
        当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知

两者的区别在哪里呢?水平触发是只要读缓冲区有数据,就会一直触发可读信号,而边缘触发仅仅在空变为非空的时候通知一次,举个例子:

    读缓冲区刚开始是空的
    读缓冲区写入2KB数据
    水平触发和边缘触发模式此时都会发出可读信号
    收到信号通知后,读取了1kb的数据,读缓冲区还剩余1KB数据
    水平触发会再次进行通知,而边缘触发不会再进行通知

所以边缘触发需要一次性的把缓冲区的数据读完为止,也就是一直读,直到读到EGAIN为止,EGAIN说明缓冲区已经空了,因为这一点,边缘触发需要设置文件句柄为非阻塞

//水平触发
ret = read(fd, buf, sizeof(buf));

//边缘触发
while(true) {
    ret = read(fd, buf, sizeof(buf);
    if (ret == EAGAIN) break;
}

    1
    2
    3
    4
    5
    6
    7
    8

epoll接口介绍

    epoll_create
        创建epoll实例,会创建所需要的红黑树,以及就绪链表,以及代表epoll实例的文件句柄
        函数原型: int epoll_create(int size);
            Man文档中说明了在老的内核版本中,入参size用来指出创建的内部数据结构的大小,目前已经可以动态调整,但是为了兼容老的版本,所以仍然保留,这个size其实意义已经不大

    epoll_ctl
        添加,修改,或者删除 注册到epoll实例中的文件描述符上的监控事件

        int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
            epfd: epoll实例file descriptor

            op:操作类型

            EPOLL_CTL_ADD, 为相应fd添加事件
            EPOLL_CTL_MOD, 修改fd的事件
            EPOLL_CTL_DEL,删除fd上的某些事件
                1
                2
                3

            fd: 操作的目标文件描述符

            event: 要操作的事件

               typedef union epoll_data {
                   void        *ptr;
                   int          fd;
                   uint32_t     u32;
                   uint64_t     u64;
               } epoll_data_t;

               struct epoll_event {
                   uint32_t     events;      /* Epoll events */
                   epoll_data_t data;        /* User data variable */
               };
               events可以是一组bit的组合
                EPOLLIN:可读
                EPOLLOUT: 可写
                EPOLLET: 边缘触发,默认是水平触发
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15

            一句话来描述:就是对于注册到epfd中的fd文件描述符,执行op event的操作
    epoll_wait
        epoll_wait等待epoll实例中注册的事件触发
        int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
            epfd: epoll实例文件描述符
            events: 数组出参,用来记录被触发的events,其大小应该和maxevents一致
            maxevents: 返回的events的最大个数,如果最大个数大于实际触发的个数,则下次epoll_wait的时候仍然可以返回
            timeout: 等待事件,毫秒为单位 -1:无限等待 0:立即返回
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值