3

epollのマンページには、EPOLLET(エッジトリガー)に登録されたfdは、読み取りが行われていない場合、EPOLLINに2回通知するべきではないと記載されています。
したがって、EPOLLINの後、epoll_waitが新しいデータで新しいEPOLLINを返すことができるようになる前に、バッファーを空にする必要があります。

ただし、手付かずのfdsに対して重複したEPOLLINイベントが表示されるため、このアプローチで問題が発生しています。
これはstrace出力です。0x200はEPOLLRDHUPであり、私のglibcヘッダーではまだ定義されていませんが、カーネルで定義されています。

30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3,  <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011

したがって、fd番号9を追加した後、ファイル記述子を受け取る前に2つの連続したEPOLLINイベントを受信します。システムコールトレースは、読み取る前にfdを削除する方法を示していますが、イベントごとに1回だけ発生するはずです。
したがって、マンページを正しく読んでいないか、ここで何かが機能しています。

4

3 に答える 3

10

epollマニュアルページのこの部分を見逃したと思います。

エッジトリガーepollを使用しても、データの複数のチャンクを受信すると複数のイベントが生成される可能性があるため、呼び出し元はEPOLLONESHOTフラグを指定して、。でイベントを受信した後に関連するファイル記述子を無効にするようにepollに指示できますepoll_wait(2)。フラグが指定されている場合、を使用しEPOLLONESHOTてファイル記述子を再作成するのは呼び出し元の責任 です。epoll_ctl(2)EPOLL_CTL_MOD

つまり、最初にread()発生する前に2つのチャンクのデータが受信キューに到着しました。つまり、2つのepollイベントが発生しました。それはEPOLLONESHOTあなたが求めているもののようです。これは、イベントが発生したときにポーリングセットからファイル記述子をアトミックに削除します(したがって、を実行する必要はありませんEPOLL_CTL_DEL)。

于 2010-04-20T10:02:33.763 に答える
2

エッジトリガーとは、(EPOLLONESHOTを使用していない限り)何かが(カーネル)バッファーに入ったときに1つのイベントを取得することを意味します。

したがって、1つのEPOLLINイベントを取得し、それについて何もしなかった場合、次にその記述子にデータが到着したときに別のEPOLLINを取得します。ただし、新しいデータが到着しなければ、イベントを取得しません。最初のイベントで示されたデータを読み取ります。

于 2010-04-20T10:07:35.543 に答える
-1

簡単に言えば、EPOLLONESHOT は、読み取るはずのデータを読み取らない場合、破棄されることを意味します。

通常、それらを読み取らない場合、同じデータのイベントで通知されます。ただし、EPOLLONESHOT では、データを読み取らないことは完全に合法であり、単に無視されます。したがって、それ以上のイベントは生成されません。

于 2011-07-20T14:03:32.907 に答える