深入理解 epoll 回调用户数据

本文深入剖析了epoll的epoll_data用户数据在内核与用户层的角色,以及epoll_ctl和epoll_wait的处理流程。在用户层,epoll_data用于回调事件给用户处理,可以是fd、指针或其他类型。通过对比libco、redis、libev和nginx等开源项目的实现,探讨了不同参数传递方式的优缺点。最后强调了在实现事件驱动逻辑时需要考虑的细节和潜在问题。

epoll 多路复用驱动是异步事件处理,在用户层它提供了用户数据(epoll_data),方便事件触发后回调给用户处理。

文章来源 🔥:《深入理解 epoll 回调用户数据

  • glibc
/* sys/epoll.h */
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 */
} __EPOLL_PACKED;
  • 内核
/* eventpoll.h */
struct epoll_event {
   
   
    __poll_t events;
    __u64 data;
} EPOLL_PACKED;
  • content
    {:toc}

1. epoll_data

我们来看看 epoll 事件和接口,epoll_data 是用户数据,内核并不会处理,只与对应的 fd 绑定,当 fd 产生事件后,epoll_wait 会回调回来。

/* 用户数据。*/
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 */
} __EPOLL_PACKED;


/* 事件控制接口。 */
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

/* 事件监控回调接口 */
int epoll_wait(int epfd, struct epoll_event* events, int maxevents. int timeout);

2. 内核

走读 epoll 源码,简单走一下 epoll 事件的添加和回调流程。

参考:《[epoll 源码走读] epoll 实现原理

2.1. epoll_ctl

监控的 fd 事件信息,被添加到内核红黑树节点进行监控。

/* eventpoll.c */
SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event) {
   
   
    struct epoll_event epds;

    if (ep_op_has_event(op) &&
        copy_from_user(&epds, event, sizeof(struct epoll_event)))
        return -EFAULT;

    return do_epoll_ctl(epfd, op, fd, &epds, false);
}

int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, bool nonblock) {
   
   
    ...
    switch (op) {
   
   
    case EPOLL_CTL_ADD:
        if (!epi) {
   
   
            epds->events |= EPOLLERR | EPOLLHUP;
            error = ep_insert(ep, epds, tf.file, fd, full_check);
        }
        ...
    }
    ...
}

static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
             struct file *tfile, int fd, int full_check
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值