더북(TheBook)

epoll에서 말하는 레벨 트리거는 “소켓이 I/O 가능하다.”를 의미합니다. 에지 트리거는 “소켓이 I/O 가능이 아니었는데, 이제 I/O 가능이 되었다.”를 의미합니다. 따라서 레벨 트리거는 I/O 가능인 이상 epoll에서 항상 꺼내어지지만, 에지 트리거는 I/O 가능이 아니었다가 가능으로 변하는 순간에만 꺼내어집니다. 여기까지만 보아도 에지 트리거를 사용하는 것이 더 적절해 보이지 않나요?

그러나 에지 트리거를 사용할 때는 조심해야 할 점이 있습니다. 예를 들어 epoll에서 소켓 S1에 대해 에지 트리거 이벤트를 꺼냈다고 가정합시다. 그리고 그 이벤트 종류가 receive라고 합시다. 소켓 S1에 대해 receive()를 실행한 후 데이터를 꺼냅니다. 그런데 S1은 UDP 소켓이고 이미 데이터그램이 2개 있습니다. receive() 실행으로 꺼낸 데이터그램은 1개이므로 아직 1개가 남아 있습니다.

자, S1은 아까도 수신 가능이었지만 receive() 함수를 호출한 후에도 여전히 수신 가능입니다. 즉, I/O 가능에 변화가 있는 것은 아닙니다. 이때 epoll은 S1의 에지 트리거만 인식하도록 설정해 놓았다고 합시다. 안타깝게도 I/O 가능의 변화가 없었으므로 epoll은 아무것도 알려 주지 않습니다. 결국 남은 데이터그램 1개는 영원히 꺼내지 못합니다.

따라서 에지 트리거를 쓸 때는 다음 사항을 주의해야 합니다.

1. I/O 호출을 한 번만 하지 말고 would block이 발생할 때까지 반복해야 합니다.

2. 소켓은 논블록으로 미리 설정되어 있어야 합니다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.