linux - 无法让 eventfd 与 epoll 一起工作
我正在编写一个基于 epoll 的简单服务器类。为了唤醒epoll_wait()
,我决定使用eventfd。据说它更适合简单的事件通信,我同意这一点。因此,我创建了我的事件并在其上放置了一个监视:
_epollfd = epoll_create1(0);
if (_epollfd == -1) throw ServerError("epoll_create");
_eventfd = eventfd(0, EFD_NONBLOCK);
epoll_event evnt = {0};
evnt.data.fd = _eventfd;
evnt.events = _events;
if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, _eventfd, &evnt) == -1)
throw ServerError("epoll_ctl(add)");
稍后在消息等待循环中,在一个单独的线程上:
int count = epoll_wait(_epollfd, evnts, EVENTS, -1);
if (count == -1)
{
if (errno != EINTR)
{
perror("epoll_wait");
return;
}
}
for (int i = 0; i < count; ++i)
{
epoll_event & e = evnts[i];
if (e.data.fd == _serverSock)
connectionAccepted();
else if (e.data.fd == _eventfd)
{
eventfd_t val;
eventfd_read(_eventfd, &val);
return;
}
}
当然,停止服务器的代码是:
eventfd_write(_eventfd, 1);
出于我无法解释的原因,我无法只需写入事件即可唤醒epoll_wait()
。最终,这在几次调试会话中发挥了作用。
这是我的解决方法:知道每次 fd 可用于写入时 EPOLLOUT
都会触发一个事件,我将停止代码更改为“
epoll_event evnt = {0};
evnt.data.fd = _eventfd;
evnt.events = EPOLLOUT;
if (epoll_ctl(_epollfd, EPOLL_CTL_MOD, _eventfd, &evnt) == -1)
throw ServerError("epoll_ctl(mod)");
现在可以工作了”,但不应该是这样。
我不认为这应该有什么困难。我做错了什么?
谢谢
I'm writing a simple server class based on epoll. In order to wake up epoll_wait()
, I decided to use an eventfd. It is said that it is better suited for simple event communication and I agree with that. So I created my event and put a watch on it:
_epollfd = epoll_create1(0);
if (_epollfd == -1) throw ServerError("epoll_create");
_eventfd = eventfd(0, EFD_NONBLOCK);
epoll_event evnt = {0};
evnt.data.fd = _eventfd;
evnt.events = _events;
if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, _eventfd, &evnt) == -1)
throw ServerError("epoll_ctl(add)");
later in the message waiting loop, on a separate thread:
int count = epoll_wait(_epollfd, evnts, EVENTS, -1);
if (count == -1)
{
if (errno != EINTR)
{
perror("epoll_wait");
return;
}
}
for (int i = 0; i < count; ++i)
{
epoll_event & e = evnts[i];
if (e.data.fd == _serverSock)
connectionAccepted();
else if (e.data.fd == _eventfd)
{
eventfd_t val;
eventfd_read(_eventfd, &val);
return;
}
}
and, of course, the code that stop the server was:
eventfd_write(_eventfd, 1);
For reasons that I can't explain, I was unable to wake up the epoll_wait()
just by writing to the event. Eventually, this worked in a few debugging sessions.
Here is my workaround: knowing that EPOLLOUT
will trigger an event every time the fd is available for writing, I changed the stop code to
epoll_event evnt = {0};
evnt.data.fd = _eventfd;
evnt.events = EPOLLOUT;
if (epoll_ctl(_epollfd, EPOLL_CTL_MOD, _eventfd, &evnt) == -1)
throw ServerError("epoll_ctl(mod)");
Now it works but It shouldn't be this way.
I don't believe this should be any difficult. What have I done wrong?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对我有用。作为参考,这里是完整的 C 代码:它打印“eventfd_write”、“1”和“DING: 1”。在 Linux 2.6.35-30-generic #56-Ubuntu SMP 上测试。
Works for me. For reference, here is the complete C code: it prints "eventfd_write", "1" and "DING: 1". Tested on Linux 2.6.35-30-generic #56-Ubuntu SMP.
如果您使用多个线程,则必须在每个线程末尾链接对
eventfd_write
的调用。这只是一种选择。If you're using multiple threads you have to chain your call to
eventfd_write
at the end of each thread. This is only one option.