Epoll 机制

描述

epoll 是poll系统调用的升级版。可以用做单边沿(level-triggered)和双边沿(edge-triggered)的两种工作模式,同样也可以用于检测多个文件描述符。

API

  • epoll_create(int size)

用于创建一个epoll的实例对象。参数size代表可以一次性检测的文件对象的个数。返回值是epoll 实例对象的文件描述符,次描述符用于后续的epoll_ctl和epoll_wait函数中,当没有对象检测的时候,需要使用close系统调用关系该文件描述符,因为epoll实际上也会占用用一个fd的。

  • epoll_ctl(int epfd, int op, int fd, struct epoll_event* event)

用于注册要检测的对象以及检测的事件。 epfd代表的是epoll的实例对象,也就是epoll_create的返回值。op代表的几种操作,如下:

EPOLL_CTL_ADD: 注册一个new的fd对象到epoll实例中。

EPOLL_CTL_MOD: 修改已经注册的fd的事件。

EPOLL_CTL_DEL: 从epoll检测的列表中remove掉fd。

event就是代表具体要检测的事件类型,详细信息如下:

struct epoll_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成员,代表具体检测的事件类型:

EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
  • epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout)

该系统调用用于等待检测对象的事件发生。 events具体返回具体的发生的事件内容,maxevents用于告知允许最大的事件数量,timout当然也就是超时时间,-1代表一直等待不超时。返回值代表发生事件需要处理的数据,返回值为0代表timeout。

实例分析

#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define EPOLL_INSTANCE_SIZE (8)
#define EPOLL_EVENTS_SIZE   (8)


int main(int argc, char** argv)
{

    int epfd;
    int i = 0;
    int events;
    struct epoll_event eventItem[EPOLL_EVENTS_SIZE];
    char buf[512];

    /*usage*/
    if(argc < 2 )
    {
        printf("Usage: %s <file1> <file2> ...\n", argv[0]);
        return -1;
    }

    /*创建epoll实例对象*/
    epfd = epoll_create(EPOLL_INSTANCE_SIZE);
    if(epfd == -1)
    {
        printf("epoll_create error!\n");
        return -1;
    }
    
    /*添加检测实例对象*/
    for(i = 1; i < argc; i++)
    {
        int fd;
        struct epoll_event event;

        fd = open(argv[i], O_RDWR);                
        event.events = EPOLLIN;
        event.data.fd = fd;
        epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
    }
 
    while(1)
    { 
        /*等待事件发生*/
        events = epoll_wait(epfd, eventItem, EPOLL_EVENTS_SIZE, -1);
        for(i = 0; i < events; i++)
        {
            int len = read(eventItem[i].data.fd, buf, 512);
            buf[len] = '\0';
            printf("read buf is %s\n",buf);
        }
    }
    
    return 0;
}

测试结果:

1. 编译代码

gcc epoll.c -o epoll

2. 在tmp创建下创建3个fifo文件

mkfifo tmp/1 tmp/2 tmp3

3. 使用epoll在后台检测

./epoll tmp/1 tmp/2 tmp/3 &

可以从/proc/epoll进程的pid/fd中看到详细信息

4. echo 数据到 tmp/1中查看结果

test$ echo 111 > tmp/1
read buf is 111

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • NULL指针的奇妙之旅

    今天带大家了解下NULL指针是如何形成的? 当然了我们要深入到操作系统中去看看为何访问一个NULL指令会报Segment Fault的错误。

    DragonKingZhu
  • Inotify机制

    Inotify API用于检测文件系统变化的机制。Inotify可用于检测单个文件,也可以检测整个目录。当检测的对象是一个目录的时候,目录本身和目录里的内容都会...

    DragonKingZhu
  • SLUB结构体创建及创建slab分析

    在上一篇文章中我们通过一个简单的例子大概描述了如何创建SLUB缓存,如何分配一个object。本文详细描述下涉及的结构体,从结构体的描述中就可以大概理解slub...

    DragonKingZhu
  • linux网络编程之socket(十三):epoll 系列函数简介、与select、poll 的区别

    一、epoll 系列函数简介 #include <sys/epoll.h> int epoll_create(int size); int epoll_cr...

    s1mba
  • Redis技术知识总结之七——Redis多路复用机制

    redis 是一个单线程却性能非常好的内存数据库, 主要用来作为缓存系统。 redis 采用网络IO多路复用技术来保证在多连接的时候, 系统的高吞吐量。 为什...

    剑影啸清寒
  • epoll,求知者离我近点

    上网一搜epoll,基本是这样的结果出来:《多路转接I/O – epoll模型》,万变不离这个标题。 但是呢,不变的事物,我们就更应该抓出其中的重点了。 多...

    看、未来
  • Linux中epoll IO多路复用机制

    epoll简介 epoll 是Linux内核中的一种可扩展IO事件处理机制,最早在 Linux 2.5.44内核中引入,可被用于代替POSIX select 和...

    小小科
  • 多路复用技术 epoll 分析

    epoll有EPOLLLT和EPOLLET两种触发模式,水平触发和边缘触发. 此处略

    平凡的学生族
  • epoll

    epoll是Linux提供的I/O event notification facility。在需要监听的fd数量很多(成千上万)而同一时刻可读/可写的数量又比较...

    linjinhe
  • select和epoll模型

    转自https://www.cnblogs.com/lojunren/p/3856290.html

    大学里的混子

扫码关注云+社区

领取腾讯云代金券