[Backend] level trigger eidge trigger 구조

1 minute read

trigger

  • Level-Trigger Notification
    • 상태 변화를 감지하고자 하는 fd가 준비되면 무조건 알리는 방식이다.
    • 어떤 이벤트가 발생하고 있는 동안에 발생하는 트리거이다.
    • 0과 1만 있는 상태에 대해서, 상태 1인 경우를 체크하기 위한 레벨 트리거는 상태가 1이면 이벤트가 발생한다. 반면에 상태가 0인 경우에는 이벤트가 발생하지 않는다.
    • 소켓에 버퍼가 있는 동안에는 계속 반환한다.
  • Edge-Trigger Notification
    • 항생 새로 준비된 fd에 대해서만 알리는 방식
    • 어떤 이벤트가 발생하는 순간에 발생하는 트리거이다.
    • 0과 1만 있는 상태에 대해서, 상태가 변하는 순간을 기준으로 동작한다. 0에서 1로 변하는 순간, 1에서 0으로 변하는 순간에 트리거가 발생한다. 0에서 0, 1에서 1로 유지되는 순간은 발생되지 않는다.
    • 만약 이벤트가 발생해서 데이터를 읽었는데, 버퍼의 데이터를 모두 읽지 않고 다음 wait 함수를 호출할 경우, wait 함수에서 봉쇄되는 문제가 생길 수 있다. 자칫하면 영원히 봉쇄될 수도 있다.
I/O 모델 Level-trigger(default) Edge-Trigger
select, poll O X
epoll O O

소켓 통신에서 trigger

소켓 통신에서 소켓 버퍼에 읽을 데이터가 있는 경우(1)와 없는 경우(0)를 가정해보자. 소켓 버퍼에 데이터 100바이트가 도착했을 때, 소켓의 상태를 0에서 1로 변경된다. 이때는 레벨 트리거와 에지 트리거 모두 이벤트를 발생시킨다. 레벨트리거는 상태가 1로 바뀌었기 때문에 이벤트로 발생시키고, 에지 트리거는 0에서 1로 상태가 변경되었기 때문에 이벤트를 발생시킨다.

이 이벤트를 처리하기 위해 사용자 앱이 소켓 버퍼에서 데이터를 읽었다고 하자. 하지만 메모리 버퍼 사이즈 제한으로 30바이트만 읽었다고 하자. 여전히 소켓 버퍼에는 70 바이트의 데이터가 남아있다. 이 경우 레벨 트리거는 여전히 데이터가 남아있기 때문에 이벤트를 발생시키고, 엣지 트리거는 발생시키지 않는다.

Edge Trigger 장점

성능보다 다음 사항 때문에 좋다.

  • 여러 스레드에서 epoll_wait 했을 때 하나의 스레드만 통보를 받는다.
  • EPOLLOUT(출력버퍼가 비워져서 당장 데이터를 전송할 수 있는 상황)로 쓰기 가능 플래그를 일일이 add/del 하지 않는다. 읽기와 달리 소켓은 대부분의 경우 쓰기 가능하므로 레벨 트리거는 플래그를 일일이 붙일 필요가 있다. 엣지 트리거는 플래그를 켜지 않아도 된다.

Edge Trigger 단점

  • 엣지트리거에서는 디스크립터 정보를 통한 수신/송신으로 EAGAIN이 왔을 때 모든 데이터를 수신/송신 했는지 확신 할 수 없다.
  • 적은 데이터 양으로 한번의 수신/송신에서는 문제 없지만 데이터 양이 많을 때는 모든 데이터를 처리했는지를 확인해야 한다. 이 조사는 애플리케이션 측에서 책임을 져야한다.
  • 즉, 각 디스립터에 대한 수신/송신을 하는 데이터를 개인 데이터 영역에 일시 저장하는 장치를 마련해야 한다.