2010-04-20 8 views
2

epoll 맨 페이지에 따르면 EPOLLET (에지 트리거 됨)에 등록 된 fd가 읽지 않은 경우 EPOLLIN에 두 번 통보해서는 안됩니다.
그래서 epoll_wait이 새 데이터에 새로운 EPOLLIN을 반환하기 전에 EPOLLIN 후에 버퍼를 비워야합니다.EPOLLET 모드의 Epoll 소켓에서 읽기 전에 2 EPOLLIN을 반환 함

그러나 필자는 수정되지 않은 fds에 대해 중복 된 EPOLLIN 이벤트를보고 있으므로이 방법에 문제가 있습니다.
이것은 strace 출력입니다. 0x200은 아직 내 glibc 헤더에 정의되어 있지 않지만 커널에 정의되어있는 EPOLLRDHUP입니다.

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를 추가 한 후 나는 콜 추적 내가 읽기 전에 FD를 삭제 할 방법을 보여줍니다 파일 기술자를 recving 가진 전에 2 개 연속 EPOLLIN 이벤트를 수신 않지만 그것은 단지 한 번 이벤트에 하나씩 발생한다 .
맨 페이지를 제대로 읽지 않거나 현재 여기서 어떤 작업을하고 있습니다.

답변

7

나는 당신이 epoll 사람 페이지의이 부분을 놓친 생각 : 심지어 에지 트리거 는 epoll 여러 이벤트와 이후 여러 데이터 청크를 수신 할 때 를 생성 할 수

을 호출자가 가지고있는 옵션을 으로 지정하면 플래그를 지정하고 은 이벤트 수신 후 파일 설명자를 사용 불가능하게 설정합니다. epoll_wait(2) 인 이벤트가 발생합니다. EPOLLONESHOT 플래그가 지정되면 epoll_ctl(2)EPOLL_CTL_MOD을 사용하여 파일 설명자를 초기화하는 것은 발신자의 책임입니다. 이다

: 당신은 첫째 read()는 두는 epoll 이벤트를 가지고 의미하는 일이 당신의 전에 수신 큐에 도착하는 두 개의 데이터 청크를 얻었다. EPOLLONESHOT은 사용자가 수행 한 작업으로, 이벤트가 발생할 때 설문 조사에서 파일 설명자를 기본적으로 제거합니다 (따라서 EPOLL_CTL_DEL을 수행 할 필요가 없습니다).

+0

좋은 답변입니다. 또 다른 질문이 있습니다 : EPOLLONESHOT이 설정되어 있다면 EPOLLET이 필요합니까? EPOLLONESHOT 이벤트를 수신하는 대부분의 시간에 fd가 IO 작업을 차단할 때까지 IO를 수행 한 다음 이벤트를 다시 설치합니다. – zach

2

에지 트리거는 EPOLLONESHOT을 사용하지 않는 한, (커널) 버퍼에 무엇인가가 들어올 때 하나의 이벤트가 발생한다는 것을 의미합니다.

따라서 EPOLLIN 이벤트가 하나라도 발생해도 아무 것도하지 않으면 다음 번에 해당 데이터가 도착할 때 다른 EPOLLIN을 받게됩니다. 새 데이터가 없으면 이벤트가 발생하지 않습니다. 첫 번째 이벤트에서 지정한대로 데이터를 읽지 않았습니다.

0

음, 간결하게 말하자면, EPOLLONESHOT은 읽어야하는 데이터를 읽지 않는다면 버려 질 것입니다.

일반적으로 읽을 수없는 경우 동일한 데이터에 대한 이벤트로 알림을받습니다. 그러나 EPOLLONESHOT을 사용하면 데이터를 읽지 않는 것이 완전히 합법적이며 무시됩니다. 따라서 더 이상 이벤트가 생성되지 않습니다.