【问题标题】:Memory handling with struct epoll_event使用 struct epoll_event 处理内存
【发布时间】:2012-10-10 13:09:31
【问题描述】:

我正在用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 结构的最佳方法是什么?

感谢您的宝贵时间。

【问题讨论】:

  • 如果“我们都知道会发生什么”,那你为什么要问?
  • 当我说“我们都知道会发生什么”时,我的意思是当函数返回时释放堆栈分配的内存。

标签: c linux epoll


【解决方案1】:

正如大家所说,struct epoll_event * 参数指向的内存可以在 epoll_ctl() 之后释放或重用。

linux/v5.8/source/fs/eventpoll.c#L2288 中,我们看到内核复制了 struct 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);
}

【讨论】:

  • 不过,我还是想知道为什么参数不是struct epoll_event const *,而是没有const。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    立即丢弃或重用您的 epoll_event 结构是绝对没问题的。

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

    这与您使用将结构作为参数的 ioctl 或使用 struct sockaddr_in 的套接字操作(例如绑定)完全相同。

    内核获取它需要的东西,你可以立即释放它。

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

    【讨论】:

    • 谢谢。赞成。不过,我会将 Kerrek SB 的答案标记为正确,因为他比您早一分钟回答。
    【解决方案4】:

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

    【讨论】:

    • 我希望此信息在联机帮助页中,并且不需要往返 SO。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    相关资源
    最近更新 更多