为什么 epoll_ctl 需要两次文件描述符?

Why does epoll_ctl need the filedescriptor twice?

示例中:

event.events = EPOLLIN;
event.data.fd = fd;

int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event.data.fd, &event);

我将文件描述符作为 event.data 的成员并作为其自身的参数传递。

什么epoll_ctl需要两次文件描述符?

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

其中:

epfd是epoll_create返回的文件描述符,用于标识内核中的epoll实例。

fd是我们要添加到epolllist/interest列表中的文件描述符。

op指的是对文件描述符fd进行的操作。一般支持三种操作:

  • 将 fd 注册到 epoll 实例 (EPOLL_CTL_ADD) 并获得有关 fd 上发生的事件的通知
  • Delete/deregister 来自 epoll 实例的 fd。这意味着该进程将不再收到有关该文件描述符 (EPOLL_CTL_DEL) 事件的任何通知。如果一个文件描述符已经被添加到多个 epoll 实例,那么关闭它会将它从所有它被添加到的 epoll 兴趣列表中删除。
  • 修改fd监控的事件(EPOLL_CTL_MOD)

event 是一个指向名为 epoll_event 的结构的指针,该结构存储我们实际想要监视 fd 的事件。

epoll_event 结构的第一个字段 events 是一个位掩码,指示 fd 正在监视哪些事件。

像这样,如果 fd 是一个套接字,我们可能希望监视它是否有新数据到达套接字缓冲区 (EPOLLIN)。我们可能还想监视 fd 以获取 edge-triggered 通知,这是由 OR-ing EPOLLET 和 EPOLLIN 完成的。我们可能还想监视 fd 以了解已注册事件的发生但仅一次,并停止监视 fd 以了解该事件的后续发生。这可以通过 OR-ing 我们要为描述符 fd 设置的其他标志(EPOLLET、EPOLLIN)和 only-once 通知传递 EPOLLONESHOT 的标志来实现。所有可能的标志都可以在手册页中找到。

epoll_event 结构的第二个字段是联合字段。

Source

除了要求的上下文之外,还添加了一些额外的数据。

希望对您有所帮助!

这是 about epoll_ctl()

的副本

它需要它两次的原因是 event 里面的 data 是一个 unionepoll_ctl 不知道您是否实际提供了文件描述符或其他内容。

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