본문 바로가기
Old Posts/Linux

[Linux] 엣지 트리거(Edge Trigger, ET)와 레벨 트리거(Level Trigger, LT)의 차이점

by A6K 2021. 8. 7.

시스템에서 특정 이벤트의 발생을  감지하기 위해서 트리거(Trigger)라는 개념을 사용한다. 트리거는 원래 전기전자에서 사용하는 개념이지만 시스템 프로그래밍에서도 비슷한 개념을 사용한다. 트리거는 '레벨 트리거(Level Trigger)'와 '엣지 트리거(Edge Trigger)'로 구분할 수 있다. 

예를 들기 위해 0과 1의 값을 가질 수 있는 어떤 변수를 생각해보자. 어떤 시스템에서 이벤트를 감지할 수 있는 센서라고 생각해도 좋다. 이 변수는 조건에 따라 0이 되기도하고 1이되기도 한다. 이를 그래프로 그려보면 위 그림처럼 0과 1이 번갈아가면서 바뀌는 것처럼 그려볼 수 있다.

레벨 트리거(Level Trigger)

우선 레벨트리거는 상태 변수의 현재 상황을 기준으로 동작한다. 상태변수가 1인 경우를 체크하기 위해서는 상태변수가 1인 상황에서 이벤트가 감지되어야 한다. 상태변수가 0인 상황에서는 이벤트가 감지되면 안된다.

레벨 트리거 동작을 그림으로 그려보면 위와 같다. 상태변수가 1일 때에만 이벤트가 감지된다.(이벤트가 트리거링(Triggering) 된다고 한다) 상태변수가 1인 상황이라면 이벤트를 몇 번이고 감지해도 항상 트리거링된다.

엣지 트리거(Edge Trigger)

반면 엣지 트리거는 상태변수의 값이 변하는 순간을 기준으로 동작한다.

상태변수가 0에서 1로 변하는 순간이나 1에서 0으로 변하는 순간에 이벤트가 감지된다. 상태변수가 0에서 1로 변하는 순간을 상승엣지(Rising Edge)라고하며, 1에서 0으로 변하는 순간을 하강엣지(Falling Edge)라고 한다. 상태가 변하는 상황이 아닌 0에서 0이나 1에서 1로 유지되는 동안에는 이벤트가 감지되지 않는다. 

위 그림에서 보면 상태가 0에서 1로 전이되는 순간 에지 트리거가 이벤트를 발생시킨다. 상태가 1인 상황에서 에지 트리거를 실행시키면 다음 상승에지(0 -> 1)까지 기다리게 된다.

소프트웨어에서 트리거링 예제

소켓 통신을 예로 들어보자. 소켓 통신에서 상태변수는 커널의 소켓버퍼에 읽을 데이터가 있는 경우(상태변수 1)와 소켓버퍼가 비어있는 경우(상태변수 0)을 생각해볼 수 있다.

소켓버퍼에 데이터가 새로 100바이트 도착했다면 소켓의 상태틑 0에서 1로 변경된다. 이 순간 레벨 트리거와 에지 트리거가 모두 이벤트를 발생시킨다. 레벨트리거는 상태변수 1로 전이했기 때문이고, 에지 트리거는 0에서 1로 상태가 변경되었기 때문이다. 이 이벤트를 처리하기 위해 사용자 애플리케이션이 소켓 버퍼에서 데이터를 읽었다고 하자. 하지만 메모리 버퍼 사이즈 제한으로 30바이트만 읽었다고 하자. 여전히 소켓 버퍼에는 70바이트의 데이터가 남아있다. 이 상황에서 레벨 트리거링을 해보면 이벤트가 발생한다. 소켓 버퍼에 데이터가 남아있기 때문이다. 하지만 에지 트리거링을 해보면 이벤트가 발생하지 않는다. 상태가 1에서 1로 유지되었기 때문이다.

소켓 통신에서 에지 트리거링을 사용할 때 epoll() 등의 시스템 호출이 Hang 상태에 빠지지 않게 주의해야한다. 소켓 버퍼에 데이터가 남아있어도 에지 트리거링에서는 이벤트가 발생하지 않고 대기하기 때문이다.

일반적으로 epoll() 등을 이용해 에지 트리거링을 할 때에는 소켓을 논블록(Non-block)으로 열어서 사용하며, read()나 write()가 EAGAIN(EWOULDBLOCK) 에러를 뱉을 때에만 에지 트리거링(epoll_wait())을 한다.

댓글