問題タブ [epollet]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
linux - ソケットから読み取る前に2EPOLLINを返すEPOLLETモードのEpoll
epollのマンページには、EPOLLET(エッジトリガー)に登録されたfdは、読み取りが行われていない場合、EPOLLINに2回通知するべきではないと記載されています。
したがって、EPOLLINの後、epoll_waitが新しいデータで新しいEPOLLINを返すことができるようになる前に、バッファーを空にする必要があります。
ただし、手付かずのfdsに対して重複したEPOLLINイベントが表示されるため、このアプローチで問題が発生しています。
これはstrace出力です。0x200はEPOLLRDHUPであり、私のglibcヘッダーではまだ定義されていませんが、カーネルで定義されています。
したがって、fd番号9を追加した後、ファイル記述子を受け取る前に2つの連続したEPOLLINイベントを受信します。システムコールトレースは、読み取る前にfdを削除する方法を示していますが、イベントごとに1回だけ発生するはずです。
したがって、マンページを正しく読んでいないか、ここで何かが機能しています。
c - epollで使用しているときのノンブロッキングソケットrecvの問題
私は問題を抱えています:時々(定期的ではありませんが)recvが戻り-1
、モードerrno == EAGAIN
で使用epoll
している間。edge-triggered
コードの一部:
startup(&port)
ノンブロッキングソケット、ポートとのバインドなどを作成します。私のスクリプトは次のデータを送信します:
GET /connect?id=1&secret=1 HTTP/1.0\r\n\r\n
しかし時々この関数でrecv
返さ-1
れます(内部を呼び出すaccept_request
):
epollのmanページに書かれているように、私は取得するまで読み取り/書き込みを行う必要がありますEAGAIN
が、すでに取得しています。バッファが空にならないことを確認します。私は何を間違えますか?
UPD:興味深いことがわかりました。そのような状況が発生した場合、コードsleep(1)
で使用し、recc(...)
期待するデータを取得します。それは汚いトリックです。この問題を解決するためのより優雅なアプローチはありますか?
linux - EPOLLETでepoll_selectを使用して複数のファイル記述子を読み取る方法は?
男エポール:
2つのfdsがあるとします。1つはパッシブで、データはたまにしか利用できません。2つ目はアクティブで、データはたまにしか利用できません。
epoll_waitは、両方を読み取ることができることを返しました。ループ内で{最初の}を読み取ります(データがまだ利用可能である間に突然ブロックされる可能性があるため、epoll_waitを呼び出さずに)。
これで、最初のファイル記述子が読み取り時にEAGAINを返しました。
何をすべきか?
- (epoll_waitを呼び出さずに)ループ内の2番目のfdを読み取り続けると、最初のfdでデータが使用可能になったことを見逃す可能性があります。EAGAINなしで読み取り、読み取り、読み取りを行います。
- 2番目のfdから読み取るたびにepoll_waitに「相談」すると、前の呼び出しから何も変更されていないため、epoll_waitが突然ブロックされる可能性があります(データは最初のFDでまだ利用できず、2番目のFDでも利用できます)。
最初のFDを忘れずに、2番目のFDの処理を続行するにはどうすればよいですか?
更新:もう1つ見つかりました:man epoll_wait:
これにより、イベントがない場合でもFDのイベントを列挙できます。
epoll - エッジトリガーepollを使用して、送信をループする必要がありますか?
私はepollを使用してメディアサーバーを作成しています。fdsはすべて非ブロッキングに設定されており、エッジトリガーイベントを使用しています。EPOLLINの場合、EAGAINが返されるまでfdの読み取りをループする必要があることを知っています。しかし、書くことはどうですか?
書き込みたいときは、データをキューに入れ、fdにEPOLLOUT | EPOLLIN|EPOLLETを設定します。EPOLLOUTイベントが発生すると、キューに入れられたバッファー全体を1回のショットで書き込みます。
n> 0 && n <buf_lenの場合、EPOLLOUTをリセットして戻ります。sendをループする意味がわかりません(epollのmanページが暗示していると思います)。sendは、可能な限りすべてを取り込んだことを示しているようで、すぐに呼び出された場合はEAGAINを返します。
ここでシステムコールを排除することが最も効率的なルートですか?
c++ - epoll: 一部の EPOLLOUT イベントが失われていますか?
これは私のサーバーがどのように見えるかです:
-WorkerThread(s):
- epoll_wait を呼び出し、接続を受け入れ、fd ノンブロッキングを設定します (EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP)
- EPOLLIN イベントで EAGAIN になるまで recv を呼び出し、すべてのデータをグローバル RecvBuffer (pthread_mutex 同期) にプッシュします。
- EPOLLOUT イベント時: グローバル SendBuffer にアクセスし、現在準備ができている fd に送信するデータがある場合は、それを実行します (while ループで EAGAIN まで、またはすべてのデータが送信されるまで; パケット全体が送信されると、SendBuffer からポップします)。
-IOThread(s)
- グローバル RecvBuffer からデータを取得し、それらを処理します
- 最初にすぐに send を呼び出そうとすることで、応答を送信します。すべてのデータが送信されていない場合は、残りのデータをグローバル SendBuffer にプッシュして WorkerThread から送信します)。
問題は、サーバーがキューに入れられたすべてのデータを送信せず (SendBuffer に残っている)、クライアントの数が増えると「送信されない」データの量が増えることです。テストのために、1 つのワーカースレッドと 1 つの iothread のみを使用していますが、それ以上使用しても違いはないようです。グローバル バッファへのアクセスは、pthread_mutex で保護されています。また、私の応答データ サイズは 130k バイトです (この量のデータを送信するには、少なくとも 3 回の送信呼び出しが必要です)。反対側には、ブロッキング ソケットを使用する Windows クライアントがあります。
どうもありがとうございました!MJ
編集:
はい、デフォルトでは、送信するものがない場合でも EPOLLOUT イベントを待機しています。実装の簡素化とマニュアルページのガイドのために、私はこのようにしました。また、それに対する私の理解は次のようなものでした:
何も送信したくないときにEPOLLOUTイベントを「見逃した」としても、データを送信したいときは、EAGAINとEPOLLOUTが将来トリガーされるまでsendを呼び出すため、問題ありません(ほとんどの場合)
ここで、IN/OUT イベントを切り替えるようにコードを変更しました。
受け入れ時:
すべてのデータが送信されたとき:
IOThread で send を呼び出して EAGAIN に到達すると、次のようになります。
..そして、私は同じ動作をします。また、EPOLLET フラグを削除してみましたが、何も変わりませんでした
1 つの副次的な質問: EPOLL_CTL_MOD フラグを指定した epoll_ctl は、イベント メンバーを置き換えますか、それとも指定された引数で単に OR しますか?
EDIT3: すべてのデータが送信されるまで、または EAGAIN まで継続的に送信するように IOThread 関数を更新しました。また、すべてのデータを送信したとしても送信しようとしましたが、ほとんどの場合、非ソケットで errno 88 Socket operation を取得していました
EDIT4:「送信コード」のいくつかのバグを修正したので、キューに入れられたデータが送信されていません..送信が完了した直後にクライアントが recv を呼び出したときに取得し、クライアントの数とともに大きくなります。クライアントの send 呼び出しと recv 呼び出しの間に 2 秒の遅延を置くと (呼び出しのブロック)、実行中のクライアントの数に応じて、サーバー上のデータはほとんど失われません (クライアント テスト コードには、1 つの send と 1 つの recv 呼び出しを持つ単純な for ループが含まれています)。繰り返しますが、ET モードの有無にかかわらず試してみました。以下は、データの受信を担当する更新された WorkerThread 関数です。@Admins/Mods 問題が少し違うので、今すぐ新しいトピックを開く必要がありますか?
c - C: epoll ET を使用するデータ転送サーバーが送信バッファーをいっぱいにする
次のような状況があります。私のサーバーは、リモート サーバー (fd_server) からデータを受信し、それをクライアント (fd_client) に転送します。複数のクライアントと複数のサーバー接続を処理できるように、エッジ トリガーの epoll を使用しています。
手順:
- クライアントがサーバーに接続します。
- 私のサーバーはリモート サーバーに接続し、データを要求します。
- リモートサーバーが応答し、サーバーがデータをクライアントに転送します。
詳細:
サーバーがリモート サーバーに接続した後、fd_server が EPOLLIN フラグを使用して epoll コントロールに追加されます。サーバーはイベントを待機します。
epoll_wait が fd_server を読み取り可能として返すと、次のループに進みます。
いくつかの読み取り/書き込みの後、sctp_sendmsg が EAGAIN を返します。これは、sctp 送信バッファーがいっぱいであることを意味します。fd_server ソケットから既に読み取ったデータを失うことなく、この状況を処理するにはどうすればよいですか?
どのくらいのデータを送信できるかを事前に知る方法があるので、適切な量だけを読み取ることができますか?
c - epoll (EPOLLET) は読み取りバイト数に依存しますか?
エッジ トリガー モードで epoll を使用します。枯渇を避けるために、コードは 1 つのソケットから一度に MAX_FREAD_LENGTH バイトを読み取ります。その後、EOL が発生するまでフラグメントを組み立てます。MAX_FREAD_LENGTH が小さいと epoll が停止することに気付きました。どのサイズの読み取りブロックでも機能するはずです。512 バイトで問題なく動作しましたが、時々ハングします (EPOLLIN イベントがないことを意味します)。MAX_FREAD_LENGTH をインクリメントすると、より安定します。この問題を解決するにはどうすればよいですか?
私の質問を考えてくれてありがとう!
EPOLL 初期化
ネットイベントの登録:
ネットイベントを処理する
編集:
言い忘れましたが、epoll は他の部分とは別のスレッドで実行されます。
multithreading - エッジ トリガー、ワン ショット、マルチスレッドを使用した epoll
これは、この回答に関する質問です: https://stackoverflow.com/a/14241095/2332808 (コメントしますが、新しく作成されたアカウントは明らかにコメントできません。ノイズで申し訳ありません。epollet/multithreading のリソースを見つけるのは困難です.. .)
次のように epoll を使用することをお勧めします。
epoll_ctl()
通知をアクティブ化します (EPOLLONESHOT
使用されている場合は再アクティブ化します)。- システム入力:
read()
//エラーが発生するまでループしrecv()
ます。accept()
EAGAIN
epoll_wait()
通知を受け取る。
epoll_wait()
しかし、同じ epollfd に複数のスレッドがあると仮定すると、読み取りが完了する前にさらにデータを受信した場合、同じ fd で別のスレッドが起動されるリスクはありません (たとえば、2 つのスレッドが同じ fd を処理することになります)。 )
物事を好転させてread()
まで戻しEAGAIN
、もう一度epoll_ctl()
呼び出しread()
てまだ何もないことを確認しても (最後の読み取りと の間に何かを受け取る競合を避けるためepoll_ctl()
)...
しかしepoll_ctl()
、あなたが実際に何かを受け取っていないという保証はまだありませんread()
.
fdごとにロックを設定することは許容できる解決策だと思いますが、複数のスレッドが同じ epollfd でポーリングするエッジトリガーモードでの epoll の「承認された」使用ですか?
c++ - 1 つのソケットと 1 つのイベント -- EPOLLIN のみで epoll_wait() > 1 を実行できますか?
私が epoll_create1() で、EPOLLIN | にのみ関心があるとしましょう。ソケット1個用のエポレット。
そのソケットで epoll_wait() > 1 (timeout=-1 と仮定) になり、イベントが EPOLLIN になる可能性はありますか?
それとも、複数のパケットがあっても epoll_wait() は 1 を返しますか?
前もって感謝します。
linux - Epoll TCP エッジ トリガーによる最後の read(2) 呼び出しの必要性
非ブロッキング TCP ソケットが与えられた場合、呼び出しが
値 < を返しますbufLen
。エッジ トリガーの EPOLLIN イベントを待っても安全ですか? read
それとも、ゼロまたは EAGAIN であることを確認するために再度呼び出す必要がありますか?
私のテストでは、最後の呼び出しを削除してもすべてが機能し続けます。それがどこかで保証されているか、Linux ソース コードで保証されているか、余分な呼び出しを取り除くことができるかどうかを知りたいだけです。