epoll_ctl() 事件参数的生命周期

Lifetime of the epoll_ctl() event parameter

man page for epoll_ctl() 给出了这个签名:

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

是否应该保存 epoll_event 参数,直到我们完成所有 epoll_wait() 处理?

换句话说,这个基于epoll man page sample的代码是否正确?

int listen_sock, nfds, epollfd;

/* Code to set up listening socket, 'listen_sock', (socket(), bind(), listen()) omitted. */
epollfd = epoll_create1(0);
if (epollfd == -1) {
    perror("epoll_create1");
    exit(EXIT_FAILURE);
}

{
    /* limit ev's scope */
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listen_sock;
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
        perror("epoll_ctl: listen_sock");
        exit(EXIT_FAILURE);
    }
}

struct epoll_event events[MAX_EVENTS];
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);

我认为 epoll_event 在我们完成所有 epoll_wait() 处理之前不需要保存 因为 linux 在调用系统调用 epoll_ctl

后立即使用 copy_from_user
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);
}

这里有详细信息:https://elixir.bootlin.com/linux/latest/source/fs/eventpoll.c#L2176