- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我目前正在添加从 accept 创建的 sockfds到具有以下事件的 epoll 实例:
const int EVENTS = (
EPOLLET |
EPOLLIN |
EPOLLRDHUP |
EPOLLONESHOT |
EPOLLERR |
EPOLLHUP);
一旦事件被触发,我将其传递给处理程序线程,读取并通过具有相同标志的 epoll_ctl
重新启用 sockfd。但是,我只收到一次 EPOLLIN
事件。此外,如果我在收到第一个事件后随时终止客户端,我也不会收到挂断事件。通过阅读手册页,我认为我理解了使用 EdgeTriggered 和 OneShot 的正确方法。
下面是我正在使用的过程的一些伪代码:
const int EVENTS = (
EPOLLET |
EPOLLIN |
EPOLLRDHUP |
EPOLLONESHOT |
EPOLLERR |
EPOLLHUP);
void event_loop()
{
struct epoll_event event;
struct epoll_event *events;
events = calloc(100, sizeof event);
while (1)
{
int x;
int num_events = epoll_wait(epfd, events, 100, -1);
for (x = 0; x < num_events; x++)
{
another_thread(fd);
}
}
}
void another_thread(int fd)
{
// Read stuff until EAGAIN
struct epoll_event event;
event.data.fd = fd;
event.events = EVENTS;
epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &event);
}
当我执行 EPOLL_CTL_MOD
操作时,我没有收到任何错误,但从未收到其他事件的通知。如果我在第一个事件后让读取循环保持重复,它将读取客户端发送的所有后续数据,所以我知道数据正在进入并且 fd 仍然打开并工作。
通过检查 strace
,线程是从 clone 创建的并具有标志 CLONE_FILES
,因此所有线程共享同一个 fd 表。
为来自单独线程的读取事件重新启用 fd 的正确方法是什么?
最佳答案
However, I only receive the EPOLLIN event one time. Also, if I kill the client anytime after the first event is received, I do not get hangup events either.
epoll_ctl(2) 的手册页说:
EPOLLONESHOT (since Linux 2.6.2) Sets the one-shot behavior for the associated file descriptor. This means that after an event is pulled out with epoll_wait(2) the associated file descriptor is internally disabled and no other events will be reported by the epoll interface. The user must call epoll_ctl() with EPOLL_CTL_MOD to rearm the file descriptor with a new event mask.
在您的情况下,当您获得第一个事件时,epoll 会禁用您的 sockfd。当您使用 EPOLL_CTL_MOD
重新启用您的 sockfd 时,它会通知内核在重新注册后 收到的所有事件。因此,第一次通知和重新注册之间的任何事件都将丢失。这可能是没有获得任何挂断事件或数据的原因。
从事件中删除 EPOLLONESHOT
将更正您的代码,最终您也不需要重新启用 sockfd。
而且由于您使用的是 EPOLLET
,因此也不会有任何性能问题。
关于c - 边缘触发的 Epoll 和 oneshot 只报告一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33885439/
我有一个 oneshot 类型的服务,我希望在停用另一个服务之前运行该服务。换句话说,每当其他服务收到停用信号时,我都希望我的服务激活、运行其进程并终止。只有当我的服务完成后,其他服务才被允许停用。
在 XCTestCase 测试中,我创建了一个 NSTask 对象并将其设置为运行 printenv。然后,在 NSTask 完成后,我使用 fork 和 execv 运行了 printenv。除了一
我目前正在添加从 accept 创建的 sockfds到具有以下事件的 epoll 实例: const int EVENTS = ( EPOLLET | EPOLLIN | E
我正在尝试处理几乎完全未记录的 Android Alarm Manager Plus,并有一个非常简单的应用程序来按下按钮、设置闹钟和触发闹钟,如下所示: import 'package:flutte
我想编写一个 SOCKS 服务器,它根据客户端请求的目的地选择多个 Internet 网关之一。大体流程是 执行SOCKS5协商并从客户端获取地址信息 请求内部服务器选择互联网网关和目标 IP 联系并
我是一名优秀的程序员,十分优秀!