Socket epoll:EPOLL_CTL_MOD会重置边缘触发吗?

3

首先,将一个套接字添加到 epoll 集合中以进行边缘触发式读取:

epoll_event ev = {};
ev.data.fd = sock;
ev.events = EPOLLIN | EPOLLET;   // edge triggered reading
epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev);

现在等待数据:

result = epoll_wait(efd, events, sizeEvents, timeoutMilliseconds);

假设有超过20个字节的数据可用。但后续代码希望以10个字节的块从流中解析消息:

result = recv(sock, buffer, 10, 0);

现在,你可能会说:"如果他调用epoll_wait,即使套接字流中还有10个字节未读取,他的代码也可能挂起或超时。" 你是正确的。

但是,我的代码不会返回到epoll_wait,而是切换 epoll 标志,以便在同一套接字上发送响应。

ev.data.fd = sock;
ev.events = EPOLLOUT|EPOLLET;
epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev);

注意,EPOLLIN不再设置。 然后,代码执行标准的sendepoll_wait循环,直到完整响应被发送。

当消息响应已设置时,代码会回到边缘触发模式的读取状态:

 ev.data.fd = sock;
 ev.events = EPOLLIN | EPOLLET;
 epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev);

在等待之后:

 result = epoll_wait(efd, events, sizeEvents, timeoutMilliseconds);    

假设自上一次从套接字 sock 上读取数据以来,没有额外的数据到达,那么上述的 epoll_wait 会挂起(或者超时)吗,因为边缘级别没有改变?还是说 EPOLLIN 被切换开和关,允许边缘状态重置,因此上述的 epoll_wait 调用将立即返回,指示套接字上有可用的数据?

1
使用EPOLLET的整个目的就是你完全不需要使用EPOLL_CTL_MOD。 - undefined
@pindumb为什么?我会说恰恰相反,因为在ET模式下,即使你还没有收到客户端所需的请求,你也必须尽可能多地写入。这就是为什么你需要先阅读请求,然后切换到EPOLLOUT并写入响应的原因。 - undefined
1个回答

0
切换监视的事件仍然会导致epoll_wait()挂起。ET模式下的epoll_wait()会对监视事件所涉及的文件描述符进行更改时触发回调函数。您仍然需要等待一些新数据到达该fd,以便接收epoll_wait()的通知。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接