EPOLLET的用例是什么? [英] What is the use case for EPOLLET?

查看:55
本文介绍了EPOLLET的用例是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

epoll 是一只奇怪的野兽.它要求该过程跟踪每个受监控FD的最后响应是什么.它要求流程能够无故障地处理所报告的每个事件(否则,我们可能会认为FD实际上并没有被边缘触发行为所静音,而是没有报告任何报告).

epoll in edge trigger mode is a strange beast. It requires the process to keep track of what the last response for each monitored FD is. It mandates the process to handle, without fail, each and every event reported (or else we might think that an FD is not reporting anything whilst it is, in fact, muted by the edge trigger behavior).

边缘触发 epoll 有意义的用例是什么?

What are the use cases where edge trigger epoll makes sense?

推荐答案

我知道的 EPOLLET 的主要用例是微线程.

The main use case for EPOLLET that I'm aware of is with micro-threads.

总而言之,用户空间正在根据要处理的事情的可用性在微线程(我将之称为光纤",因为它更短)之间进行上下文切换.这也称为协作式多任务处理".

To recap - user space is doing context switches between micro-threads (which I'm going to call "fibers" because it's shorter) based on the availability of something to work on. This is also called "collaborative multi-tasking".

文件描述符的基本处理是通过包装相关的IO函数,如下所示:

The basic handling of file descriptors is by wrapping the relevant IO functions like so:

ssize_t read(int fd, void *buffer, size_t length) {
  // fd should already be in O_NONBLOCK mode
  while(true) {
    ssize_t result = ::read(fd, buffer, length); // The real read
    if( result!=-1 || (errno!=EAGAIN && errno!=EWOULDBLOCK) )
      return result;

    start_monitoring(fd, READ);
    wait_event();
  }
}

start_monitoring 是一项确保对 fd 进行读取可用性监视的功能. wait_event 执行上下文切换,直到调度程序重新唤醒该光纤为止,因为 fd 现在已准备好读取数据.

start_monitoring is a function that makes sure that fd is monitored for read availability. wait_event performs a context switch out until the scheduler re-awakens this fiber because fd now has data ready for reading.

使用 epoll 实现此目的的通常方法是在 start_monitoring 中的 fd 上调用 EPOLL_CTL_MOD 代表 EPOLLIN ,并在epoll报告该事件后停止监听 EPOLLIN .

The usual way to implement this with epoll is to call EPOLL_CTL_MOD on fd within start_monitoring to add listening for EPOLLIN, and again after the epoll has reported the event to stop listening for EPOLLIN.

这意味着具有数据可用的 read 将在1个系统调用内完成,但是返回 EAGAIN 的read将至少花费 4个系统调用(原始的 read ,两个 EPOLL_CTL_MOD 和成功的最后一个 read ).

This means that a read that has data available will finish within 1 system call, but a read that returns EAGAIN will take at least 4 system calls (original read, two EPOLL_CTL_MOD, and the final read that succeeds).

请注意,以上内容不计算也必须发生的.我不算数,因为我大胆地假设其他光纤也将被同一系统调用唤醒,因此将其成本全部归因于我们的光纤是不公平的.总之,此机制需要4 + x个系统调用,其中x在0到1之间.

Notice that the above does not count the epoll_wait that also has to take place. I do not count it because I'm taking the generous assumption that other fibers are also about to be woken with that same system call, so it is unfair to attribute its cost entirely to our fiber. All in all, this mechanism needs 4+x system calls, where x is between 0 and one.

降低成本的一种方法是使用 EPOLLONESHOT .这样做会自动将 fd 从监视中删除,从而将我们的成本降低到3 + x.更好,但是我们可以做得更好.

One way to reduce the cost is to use EPOLLONESHOT. Doing so removes fd from monitoring automatically, reducing our cost to 3+x. Better, but we can do better yet.

输入 EPOLLET .先前的 fd 状态可以为布防或不布防(即-下一个事件是否会触发 epoll ).另外,fd当前(在进入 read 时)可能已经准备就绪,也可能没有.四个州.让我们散布它们.

Enter EPOLLET. The previous fd state can be either armed or unarmed (i.e. - whether the next event will trigger the epoll). Also, the fd may or may not currently (at the point of entry to read) have data ready. Four states. Let's spread them out.

Ready(无论是否武装):第一次调用 read 返回数据.1个系统调用.该路径不会改变武装状态,准备状态取决于我们是否阅读了所有内容.

Ready (whether armed or not): The first call to read returns the data. 1 system call. This path does not change the armed state, and ready state depends on whether we read everything.

未准备好(无论是否布防):第一次调用 read 会返回 EAGAIN ,从而布防了fd.我们在 wait_event 中入睡,而不必执行另一个系统调用.一旦我们醒来,我们就处于未武装模式(就像我们刚刚醒来一样).因此,我们不需要调用 epoll_ctl 来禁用对fd的监听.我们调用 read 返回数据.我们使该功能准备就绪或未准备就绪,但没有武装.

Not ready (whether armed or not): The first call to read returns EAGAIN, thus arming the fd. We go to sleep in wait_event without having to execute another system call. Once we wake up, we are in unarmed mode (as we just woke up). We thus do not need to call epoll_ctl to disable listening on the fd. We call read which returns the data. We leave the function either ready or not, but unarmed.

总费用:2 + x.

随着 fd 开始武装,我们将不得不面对每个 fd 一次虚假的唤醒.我们的代码必须处理 epoll 报告没有光纤正在监听的fd的情况.在这种情况下,处理只是意味着忽略并继续前进.不会再次虚假报告该FD.

We will have to face one spurious wakeup per fd, as the fd starts out armed. Our code will have to handle the case where epoll reports an fd for which no fiber is listening. Handling, in this case, just means ignore and move on. The FD will not be spuriously reported again.

这篇关于EPOLLET的用例是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆