使用struct epoll_event处理内存

时间:2012-10-19 20:58:58

标签: c linux epoll

我正在使用epoll library在C中开发一个服务器,我对如何处理struct epoll_event的内存有疑问。我在一些在线示例中注意到,在进行epoll_ctl调用时,会在堆栈上分配events参数,然后传递指针,如下所示:

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

现在我们都知道函数返回时ev会发生什么。我的问题是:epoll库是否在内部复制这些值,还是依赖于您传递给堆分配的结构?上面的例子会完全破坏我的反应堆实现吗?如果是这样,跟踪我的堆分配epoll_event结构的最佳方法是什么?

感谢您的时间。

4 个答案:

答案 0 :(得分:12)

一切都很好。 epoll_ctl函数是一个简单的系统调用包装器,当函数返回时它将完全完成。不需要来自用户空间的更多数据。结构只是一种打包参数的方法。

答案 1 :(得分:8)

立即丢弃或重复使用epoll_event结构是绝对正确的。

内核会将参数复制出epoll_event结构。

这与使用带有struct作为参数的ioctl或带有struct sockaddr_in的套接字操作(例如bind)完全相同。

内核可以满足它的需要,你可以立即释放它。

您唯一需要担心的是“用户数据”,它只与您相关。内核将存储它,但是当你得到一个事件时你需要知道它意味着什么。

答案 2 :(得分:4)

epoll是一组系统调用,而不是库。当您调用epoll系统调用时,您进入内核,并且内核通常不信任这些用户模式缓冲区必须有效或坚持,而是通过copy_from_user等复制到内核内存中。所以是的,你可以在堆栈上设置结构,将它们的地址传递给系统调用,然后在它返回后丢弃它们。

答案 3 :(得分:0)

众所周知,struct epoll_event *参数指向的内存可以在epoll_ctl()之后释放或重用。

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