[TIL] 소켓 프로그래밍 - epoll

KYJ의 Tech Velog·2024년 2월 29일
0

epoll은 I/O 가능 상태가 된 소켓을 감지해서 사용자에게 알림을 주는 역할을 합니다.

여러 소켓 중에 한 소켓이 I/O 가능이 되는 순간 epoll은 이 상황을 epoll 안에 내장된 큐에 추가합니다. 사용자는 이 큐에서 이러한 이벤트 정보를 꺼낼 수 있습니다. 이렇게 어떤 소켓이 I/O 가능인지 알 수 있습니다. 따라서, 소켓의 개수와 상관없이 I/O 가능인 소켓들만 확인할 수 있습니다.

epoll은 리눅스와 안드로이드에서만 사용 가능하다고 합니다. (iOS, MacOS, FreeBSD에서는 유사한 kqueue가 존재)

epoll을 활용하면 반복문을 돌지 않아도 되기 때문에 연산을 많이 줄일 수 있습니다. 이는 이상적으로 보이지만 현실은 상황이 다릅니다. 실제로는 소켓의 송신 버퍼가 빈 공간이 없는 순간을 유지하는 시간이 상대적으로 짧습니다. 거의 대부분은 송신 가능입니다.

결국은 필요 이상으로 반복문을 돌기 때문에 불필요한 CPU 연산 낭비가 발생합니다. 이를 해결하기 위해서는 레벨 트리거가 아닌 에지 트리거를 사용해야 합니다. 전자공학에서 나온 용어로 추정컨대, 레벨은 전압 자체가 있음을 의미하고, 에지는 전압의 변화가 있음을 의미합니다.

epoll에서 이야기 하는 레벨 트리거는 소켓이 I/O 가능하다를 의미합니다. 에지 트리거는 소켓이 I/O 가능이 아니었는데, I/O 가능이 되었다를 의미합니다. 레벨 트리거를 사용하면 I/O 가능인 상황을 항상 꺼내지만, 에지 트리거는 I/O 가능이 아니었다가 가능으로 변하는 순간에만 꺼냅니다.

다만, 에지 트리거를 사용할 때도 주의해야 할 점은 있습니다. UDP 소켓에 대해 수신 함수를 실행하는 상황을 가정해보겠습니다. 만약 이미 데이터그램이 2개 있는 상황에서 수신 함수가 실행되면 1개의 데이터그램이 꺼내지고 1개가 남게 됩니다. 이전에도 수신 가능이었지만 수신 함수를 실행한 후에도 수신 가능이 됩니다. 이러한 상황에 에지 트리거를 사용한다면 epoll은 아무것도 알려주지 않을 것입니다.

결국 에지 트리거는 다음 사항을 주의해야만 합니다.

  1. I/O 호출을 would block이 발생할 때까지 반복
  2. 소켓은 논블록 미리 설정

또한, 연결 함수는 송신 함수, 승인 함수는 수신 함수와 똑같이 취급됩니다.

0개의 댓글