epollo

epollo 的核心是3个api,它们分别是:

  • int epollo_create(int size)
  • int epollo_ctl(int epfd,int op, int fd, struct epoll_event *event)
  • int epollo_wait(int epfd, stuct epoll_event *events, int maxevents, int timeout)

epollo 的数据结构是1个红黑树和1个链表:

函数解释

int epollo_create(int size)

功能:内核产生一个 epollo 实例数据结构,并返回一个文件描述符 epfd,这个特殊的文件描述符就是 epollo 实例的句柄。size 参数表示要监听文件描述符的最大值,不过已经在后来的 linux 版本中被废弃。

int epollo_ctl(int epfd,int op, int fd, struct epoll_event *event)

功能:用于存储所有监听文件描述符,当添加或者删除一个套间字时,都在红黑树上去处理,红黑树本身插入和删除性能比较好,时间复杂度是 O(logN).
参数:

  • epfd:epoll 实例
  • op 操作类型:
    • EPOLL_CTL_ADD:添加一个需要监听的文件描述符
    • EPOLL_CTL_DEL:删除一个已经监听了的文件描述符
    • EPOLL_CTL_MOD:修改已经注册的文件描述符监听的而事件
  • fd:文件描述符
  • epollo_event:表示要监听什么事件

epollo_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队列里。

int epollo_wait(int epfd, stuct epoll_event *events, int maxevents, int timeout)

功能:阻塞等待注册的事件发生,返回事件的数目,并将触发的事件写入到 events 数组中。
参数:

  • maxevents:返回的 events 的最大个数
  • timeout:表示在函数调用中阻塞时间上限,单位是 ms
    • -1:表示一直阻塞,直到有文件描述符进入 ready 状态或者捕获到信号才返回
    • 0:用于非阻塞检测是否有描述符处于ready 状态,立即返回
    • 大于0:表示调用将最多持续timeout时间,如果期间有检测对象变为 ready 状态或者捕获到信号则返回,否则直到超时

参考:https://zhuanlan.zhihu.com/p/159135478

posted @ 2022-03-19 20:26  莫己若  阅读(61)  评论(0编辑  收藏  举报