簡體   English   中英

什么時候用邊緣模式和 oneshot 重新裝備 epoll?

[英]When to rearm epoll with edge mode & oneshot?

我正在為套接字編寫一個協程包裝器作為協程用例的演示,並且我在如何安全地使用 epoll(不引入競爭條件)方面有點掙扎。

我已經發現我必須將邊緣模式EPOLLETEPOLLONESHOT EPOLLET使用。 但現在我不確定什么時候應該重新裝上插座。

我應該在調用非阻塞操作之前還是之后重新武裝? 我想確保我既不會錯過活動,也不會收到幻影。

// epoll & socket setup

int ret;

ret = epoll_ctl(epoll_, EPOLL_CTL_MOD, ...); // rearm here
//...
ret = read(...);
//...
ret = epoll_ctl(epoll_, EPOL_CTL_MOD, ...); // or here?

int ret = epoll_wait(...);

我應該在調用非阻塞操作之前還是之后重新武裝?

從技術上講,之后,但並沒有那么簡單。

不管EPOLLONESHOTEPOLLONESHOT ,一旦您收到一個邊緣觸發的事件,表明給定文件描述符的讀取准備就緒,您必須考慮該 FD 繼續准備就緒,直到它的read()失敗並且errno設置為EAGAIN (因此文件必須處於非阻塞模式)。 在這些讀取過程中,您可能會使用一個read()讀取所有剩余的字節,但在下一個之前到達更多字節。 在這種情況下,如果 FD 仍處於布防狀態,那么它的新事件將排隊(或與該 FD 的另一個事件合並,視情況而定)。 在這種情況下,您可能會在實際上 FD 不再准備好時收到事件。

您應該考慮只接受那些“幻影”事件。 由於您的文件將處於非阻塞模式,因此它們不會導致不必要的停頓,只需做一些額外的工作。 你的代碼會更簡單。 但是,如果您確實使用EPOLLONESHOT來避免接收幻象事件,則在確定 FD 未准備好(通過EAGAIN read失敗)之前,您不得重新裝備 FD,否則您就無法達到目的。

因此,完整的答案是在 FD 確定為 unready 之后 這至少需要兩個read() ,可能更多。 如果文件在最后一次讀取之后和重新准備之前准備好,那么重新准備應該會導致一個適當的事件排隊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM