libevent深入浅出
  • Libevent深入浅出
  • 1 Libevent官方
  • 2 epoll
    • 2.1 流-IO操作-阻塞
    • 2.2 解决阻塞死等待的办法
    • 2.3 什么是epoll
    • 2.4 epollAPI
    • 2.5 触发模式
    • 2.6 简单的epoll服务器
  • 3 epoll和reactor
    • 3.1 reactor反应堆模式
    • 3.2 epoll的反应堆模式实现
  • 4 event_base
    • 4.1 创建event_base
    • 4.2 检查event_base后端
    • 4.3 释放event_base
    • 4.4 event_base优先级
    • 4.5 event_base和fork
  • 5 事件循环event_loop
    • 5.1 运行循环
    • 5.2 停止循环
    • 5.3 转储event_base的状态
  • 6 事件event
    • 6.1 创建事件
    • 6.2 事件的未决和非未决
    • 6.3 事件的优先级
    • 6.4 检查事件状态
    • 6.5 一次触发事件
    • 6.6 手动激活事件
    • 6.7 事件状态之间的转换
  • 7 数据缓冲Bufferevent
    • 7.1 回调和水位
    • 7.2 延迟回调
    • 7.3 bufferevent 选项标志
    • 7.4 使用bufferevent
    • 7.5 通用bufferevent操作
      • 7.5.1 释放bufferevent操作
      • 7.5.2 操作回调、水位和启用/禁用
      • 7.5.3 操作bufferevent中的数据
      • 7.5.4 bufferevent的清空操作
  • 8 数据封装evBuffer
    • 8.1 创建和释放evbuffer
    • 8.2 evbuffer与线程安全
    • 8.3 检查evbuffer
    • 8.4 向evbuffer添加数据
    • 8.5 evbuffer数据移动
    • 8.6 添加数据到evbuffer前
  • 8 链接监听器evconnlistener
    • 8.1 创建和释放 evconnlistener
    • 8.2 启用和禁用 evconnlistener
    • 8.3 调整 evconnlistener 的回调函数
    • 8.4 检测 evconnlistener
    • 8.5 侦测错误
  • 9 libevent常用设置
    • 9.1 日志消息回调设置
    • 9.2 致命错误回调设置
    • 9.3 内存管理回调设置
    • 9.4 锁和线程的设置
    • 9.5 调试事件的使用
  • 10 基于libevent服务器
    • 10.1 Hello_World服务器(基于信号)
    • 10.2 基于事件服务器
    • 10.3 回显服务器
    • 10.3 libevent实现http服务器
    • 10.4 libevent实现TCP/IP服务器
Powered by GitBook
On this page

Was this helpful?

  1. 2 epoll

2.4 epollAPI

Previous2.3 什么是epollNext2.5 触发模式

Last updated 6 years ago

Was this helpful?

2.4.1 创建EPOLL

/**
 * @param size 告诉内核监听的数目
 *
 * @returns 返回一个epoll句柄(即一个文件描述符)
 */
int epoll_create(int size);
int epfd = epoll_create(1000);

2.4.2 控制EPOLL

/**
 * @param epfd 用epoll_create所创建的epoll句柄
 * @param op 表示对epoll监控描述符控制的动作
 *
 * EPOLL_CTL_ADD(注册新的fd到epfd)
 * EPOLL_CTL_MOD(修改已经注册的fd的监听事件)
 * EPOLL_CTL_DEL(epfd删除一个fd)
 *
 * @param fd 需要监听的文件描述符
 * @param event 告诉内核需要监听的事件
 *
 * @returns 成功返回0,失败返回-1, errno查看错误信息
 */
int epoll_ctl(int epfd, int op, int fd, 
            struct epoll_event *event);


struct epoll_event {
 __uint32_t events; /* epoll 事件 */
 epoll_data_t data; /* 用户传递的数据 */
}

/*
 * events : {EPOLLIN, EPOLLOUT, EPOLLPRI, 
            EPOLLHUP, EPOLLET, EPOLLONESHOT}
 */

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

new_event.events = EPOLLIN | EPOLLOUT;
new_event.data.fd = 5;

epoll_ctl(epfd, EPOLL_CTL_ADD, 5, &new_event);

2.4.3 等待EPOLL

/**
 *
 * @param epfd 用epoll_create所创建的epoll句柄
 * @param event 从内核得到的事件集合
 * @param maxevents 告知内核这个events有多大,
 *             注意: 值 不能大于创建epoll_create()时的size.
 * @param timeout 超时时间
 *     -1: 永久阻塞
 *     0: 立即返回,非阻塞
 *     >0: 指定微秒
 *
 * @returns 成功: 有多少文件描述符就绪,时间到时返回0
 *          失败: -1, errno 查看错误
 */
int epoll_wait(int epfd, struct epoll_event *event, 
            int maxevents, int timeout);
struct epoll_event my_event[1000];

int event_cnt = epoll_wait(epfd, my_event, 1000, -1);

2.4.4 epoll编程框架

//创建 epoll
int epfd = epoll_crete(1000);

//将 listen_fd 添加进 epoll 中
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd,&listen_event);

while (1) {
    //阻塞等待 epoll 中 的fd 触发
    int active_cnt = epoll_wait(epfd, events, 1000, -1);

    for (i = 0 ; i < active_cnt; i++) {
        if (evnets[i].data.fd == listen_fd) {
            //accept. 并且将新accept 的fd 加进epoll中.
        }
        else if (events[i].events & EPOLLIN) {
            //对此fd 进行读操作
        }
        else if (events[i].events & EPOLLOUT) {
            //对此fd 进行写操作
        }
    }
}