简体   繁体   中英

Memory handling with struct epoll_event

I'm developing a server in C with the epoll library and I have a question as to how memory is handled for struct epoll_event . I've noticed in some online examples that, when making epoll_ctl calls, the events argument is allocated on the stack and then the pointer is passed, like so:

struct epoll_event ev;
ev.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);

Now we all know what happens to ev when the function returns. My question is: does the epoll library make copies of these values internally or does it rely on the struct you passed to be heap allocated? Will the above example totally break my reactor implementation? If so, what is the best way of keeping track of my heap allocated epoll_event structs?

Thanks for your time.

Everything is fine. The epoll_ctl function is a simple wrapper around a system call which will be entirely complete when the function returns. No further data from userspace is required. The struct is simply a way to package the arguments.

It's absolutely fine to immediately throw away or reuse your epoll_event struct.

The kernel will copy the parameters out of the epoll_event struct.

This is exactly the same as if you used an ioctl which takes a struct as a parameter, or a socket operation (eg bind) which takes a struct sockaddr_in.

The kernel takes what it needs, and it's immediately ok for you to free it.

The only thing you need to worry about is the "user data", which is only relevant to you. The kernel will store it, but you need to know what it means when you get an event.

epoll is a set of syscalls, not a library. When you call the epoll syscalls you enter the kernel, and the kernel generally doesn't trust these user mode buffers to necessarily be valid or stick around, but rather copies into kernel memory via copy_from_user etc. So yes, you can set up structs on the stack, pass their addresses to the syscall, then discard them after it returns.

As all say, the memory the struct epoll_event * parameter points to can be freed or reused after epoll_ctl().

In linux/v5.8/source/fs/eventpoll.c#L2288 , we see the kernel makes a copy of the struct epoll_event, that confirms what we believe.

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM