简体   繁体   English

使用 struct epoll_event 处理内存

[英]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 .我正在使用epoll 库在 C 中开发一个服务器,我有一个关于如何为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:我在一些在线示例中注意到,在进行epoll_ctl调用时, events参数在堆栈上分配,然后传递指针,如下所示:

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.现在我们都知道函数返回时ev会发生什么。 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?我的问题是:epoll 库是在内部复制这些值还是依赖于您传递给堆分配的结构? 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?如果是这样,跟踪我的堆分配的epoll_event结构的最佳方法是什么?

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. epoll_ctl函数是一个简单的系统调用包装器,当函数返回时它将完全完成。 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.立即丢弃或重新使用您的 epoll_event 结构绝对没问题。

The kernel will copy the parameters out of the epoll_event struct.内核将从 epoll_event 结构中复制参数。

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.这与使用将结构作为参数的 ioctl 或将 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. epoll是一组系统调用,而不是库。 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.当你调用epoll系统调用时,你进入了内核,内核通常不相信这些用户模式缓冲区一定有效或坚持下去,而是通过copy_from_user等复制到内核内存中。所以是的,你可以设置结构堆栈,将它们的地址传递给系统调用,然后在返回后丢弃它们。

As all say, the memory the struct epoll_event * parameter points to can be freed or reused after epoll_ctl().众所周知, struct epoll_event *参数指向的内存可以在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.linux/v5.8/source/fs/eventpoll.c#L2288中,我们看到内核复制了 epoll_event 结构,这证实了我们的看法。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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