TIL 115 - Polling vs Interrupt

김영현·2025년 1월 9일
0

TIL

목록 보기
125/129

Polling

Polling은 다른 장치의 상태를 주기적으로 검사한다는 의미다.
예를들어 HTTP통신에서 실시간 통신을 구현하는 방법중 하나가 있다.

setInterval(() => {
	fetch(....);
}, 1000);

통신이 언제 발생할지 정확히 모르기 때문에 특정 주기마다 서버에 요청을 보낸다. 주체는 클라이언트이며 대상은서버다.

위처럼 소프트웨어 레벨의 폴링도 있고, 하드웨어 레벨의 폴링도 있다. I/O를 예로 들어보자.
USBPolling방식을 이용하여 CPU와의 입출력을 담당한다.


출처는 위키백과

USB를 이용한 키보드(마우스등) 또한 Polling방식을 이용한다.
이처럼 Polling은 컴퓨터에 있어서 아주 기본적인 매커니즘이라고 할 수 있다.


Interrupt

Interrupt는 주기적으로 검사하는 Polling과 다르게, 특정한 상황에만 반응한다.
=> 비동기적으로 동작한다.

예를들어 HTTP통신에서 실시간 통신을 구현하는 방법중 하나인 SSE(server-sent-event)
SSE는 서버에서 클라이언트측으로 이벤트를 보낸다.

const SSE = require('sse')// npm sse 패키지

const sse = new SSE(server)//웹서버 인스턴스 등록

sse.on('connection', (client) => {
	//클라이언트에 데이터 전송...
  	client.send(someData)
})

이렇게 소프트웨어 레벨에서도 사용하지만, 보통 I/O를 처리할때 사용한다.

우리가 예전에 사용하던 키보드 PS/2(Personal System/2)방식은 Interrupt방식을 사용한다.


이미지 출처는 위키백과

왜냐면 Interrupt방식은 Polling에 비해 개발비용이 조금 더 들지만, 프로세스의 초당 처리량을 절감할 수 있기 때문이다.
옛날 컴퓨터는 프로세스 초당 처리량이 현재 컴퓨터에 비해 많이 낮았다.

I/O장치중 하나인 저장장치 또한 Interrupt를 사용한다.

Interrupt의 주체는 CPU가 아닌 디바이스인 것이다. 디바이스가 CPU에게 메시지를 보내는..


Polling과 Interrupt의 차이

특성폴링 (Polling)인터럽트 (Interrupt)
주체CPU가 상태를 확인디바이스가 CPU에 신호를 보내며 CPU가 반응
작동 방식주기적으로 상태를 확인상태 변화가 발생했을 때만 신호를 받음
자원 소모지속적으로 CPU 자원을 소모상태 변화가 있을 때만 CPU 자원을 소모
효율성비효율적 (상태 변화가 없어도 계속 확인)효율적 (변화가 있을 때만 반응)

두 방식의 차이점을 간단히 요약해보았다.


번외) EventListener는 Polling인가?

  1. Polling은 주기적으로 상태를 체크한다.
  2. EventListener는 특정한 이벤트가 발생할 시, trigger된다.
  3. trigger된다는 건, not trigger상태도 알아야한다는 의미다.
  4. 따라서 주기적으로 상태를 감시하고 있어야 한다.
  5. 그렇다면 낮은 레벨에서 Polling하고 있다는 것 아닐까?

이러한 사고의 흐름에 따라 이런 바보같은 생각이 들었다. 비전공자여서 그런지 명쾌한 해답이 바로 나오질 않았다.
그래서 열심히 찾아보니까 나와 같은 생각을 한 사람이 꽤 있었다!(바보들ㅎㅇ) 😮

이하 원문을 GPT로 돌려 번역한 내용을 요약해보았다.

첫번째 글

  1. 소프트웨어 이벤트

    • 큰 규모의 이벤트: 예를 들어, 쉘이 자식 프로세스의 종료를 기다리거나, 한 프로세스가 다른 프로세스의 메시지를 기다리는 경우. 이러한 이벤트는 반복적인 폴링(주기적인 확인)을 피하는 것이 좋습니다. 대신, 세마포어나 wait() 시스템 호출을 사용하여 대기 프로세스가 스스로 멈추고, 이벤트 발생 시 운영체제가 해당 프로세스를 깨워서 계속 실행하도록 합니다.

    • 작은 규모의 이벤트: 멀티스레드 프로그램에서 스핀 락(spin lock)을 사용해 이벤트를 기다리기도 합니다. 스핀 락은 CPU 자원을 계속해서 소비하며 대기하는 방식입니다. 최신 CPU에서는 MONITOR/MWAIT 명령어로 대기 중에 저전력 상태로 들어가기도 하며, 속도가 중요한 경우 사용됩니다.

  2. 하드웨어 이벤트

    • 하드웨어 이벤트는 인터럽트와 폴링 방식으로 처리됩니다.
      • 인터럽트: I/O 장치가 CPU에 서비스 요청을 할 때 발생합니다. 인터럽트는 CPU의 현재 작업을 중단시키고 즉시 인터럽트 서비스 루틴을 실행시킵니다. 이 방식은 드문 이벤트에 빠르게 반응할 수 있습니다 (예: 디스크 I/O 완료, 키보드 입력).
      • 폴링: 장치 드라이버가 주기적으로 상태를 확인하여 이벤트를 처리하는 방식입니다. 예를 들어, CPU 온도 점검과 같이 정기적인 체크가 필요한 경우 사용됩니다.
  3. 인터럽트와 폴링의 혼합

    • 일부 드라이버는 인터럽트와 폴링을 혼합하여 사용합니다. 예를 들어, 네트워크 드라이버는 패킷이 오지 않는 동안 인터럽트를 사용하고, 데이터가 들어오면 폴링을 통해 지속적으로 처리할 수 있습니다.

결론 : 소프트웨어 이벤트는 주로 세마포어와 같은 구조를 통해 대기하며, 이는 폴링을 사용하지 않습니다. 하드웨어 이벤트는 인터럽트와 폴링 방식으로 처리됩니다. 각 방식은 상황에 따라 효율성을 최적화하기 위해 선택적으로 사용됩니다.

출처 : https://www.quora.com/In-computer-programming-we-were-often-asked-to-use-event-listening-instead-of-polling-frequently-Arent-the-two-based-on-the-same-mechanism-deep-down-in-that-in-order-to-listen-events-the-program-has-to-periodically

그러니까...

소프트웨어 이벤트는 세마포어 구조를 통해 대기한다. 이는 폴링을 사용하지 않는다. 다만, 작은 규모의 이벤트 (멀티스레드 프로그램)에서는 스핀 락이라는 폴링방식을 이용하여 대기하기도 한다.

궁금증이 조금 해소되었지만, 명쾌하진 않다.

두번째 글

용어 정의

  • 이벤트(event): 발생할 수 있는 일의 유형.
  • 이벤트 발화(event firing): 이벤트가 발생한 특정 시점.
  • 이벤트 리스너(event listener): 이벤트 발화를 감지하는 역할을 하는 것.
  • 이벤트 핸들러(event handler): 이벤트 리스너가 이벤트 발화를 감지하면 실행되는 것.
  • 이벤트 구독자(event subscriber): 이벤트 핸들러가 호출해야 할 응답.

이 정의들은 구현에 의존하지 않으므로, 다양한 방식으로 구현될 수 있습니다.

이 용어들 중 일부는 종종 동의어로 혼동되는데, 사용자가 이들 간의 차이를 구별할 필요가 없기 때문입니다.

일반적인 시나리오

프로그래밍 논리 이벤트

  • 이벤트: 어떤 메서드가 호출되는 것.
  • 이벤트 발화: 특정 메서드가 호출된 시점.
  • 이벤트 리스너: 이벤트 메서드 내의 후크로, 각 이벤트 발화에서 이벤트 핸들러를 호출하는 역할.
  • 이벤트 핸들러: 여러 이벤트 구독자를 호출하는 것.
  • 이벤트 구독자: 이벤트 발생에 대응하여 시스템이 의도하는 작업을 수행하는 것.

외부 이벤트

  • 이벤트: 관찰 가능한 것에서 추론할 수 있는 외부적인 사건.
  • 이벤트 발화: 외부 사건이 발생했다고 인식되는 시점.
  • 이벤트 리스너: 이벤트 발화를 감지하는 방법으로, 종종 관찰 가능한 객체를 폴링하여 이벤트 발화를 인식하고 이벤트 핸들러를 호출함.
  • 이벤트 핸들러: 여러 이벤트 구독자를 호출하는 것.
  • 이벤트 구독자: 이벤트 발생에 대응하여 시스템이 의도하는 작업을 수행하는 것.

폴링 vs 이벤트 발화 메커니즘에 후크 삽입

다른 사람들이 지적한 점은, 폴링이 반드시 필요하지 않다는 것입니다. 이는 이벤트 발화가 자동으로 이벤트 핸들러를 호출하는 방식으로 구현될 수 있기 때문입니다. 시스템 수준의 이벤트일 경우, 이는 종종 가장 효율적인 방법입니다.

비유하자면, 만약 우체국 직원이 당신의 문을 두드려서 우편물을 직접 전달한다면, 매일 우편함을 확인할 필요가 없습니다.

하지만 이벤트 리스너는 폴링 방식으로도 작동할 수 있습니다. 폴링이 반드시 특정 값이나 다른 관찰 가능한 것들을 체크하는 것을 의미하지는 않지만, 기본적으로 폴링의 목적은 이벤트가 발생했을 때 이를 응답할 수 있도록 추론하는 것입니다.

비유하자면, 우체국 직원이 우편물을 우편함에 넣는다면 매일 우편함을 확인해야 할 것입니다. 하지만 우체국 직원에게 문을 두드리라고 지시할 수 있다면, 그럴 필요는 없겠죠. 다만, 그런 기능은 종종 제공되지 않습니다.

이벤트 논리 체이닝

많은 프로그래밍 언어에서 키보드 키가 눌리거나 특정 시간이 될 때 이벤트를 처리할 수 있습니다. 이 경우 외부 이벤트지만, 폴링을 필요로 하지 않습니다. 왜냐하면 운영 체제가 대신 폴링을 하기 때문입니다. 예를 들어, Windows는 키보드 상태 변경을 확인하고, 이를 감지하면 이벤트 구독자들에게 호출을 합니다. 따라서 키보드 키 눌림 이벤트에 구독하는 것은 폴링 메커니즘을 통해 체이닝된 이벤트에 구독하는 것과 같습니다.

비유하자면, 아파트 단지에 살고 있는데, 우체국 직원이 공동 우편 수령소에 우편물을 놓고, 운영 체제와 유사한 사람이 모든 우편물을 확인하여 각 아파트로 전달하는 것과 같습니다. 이렇게 하면 나머지 사람들은 우편 수령소를 폴링할 필요가 없습니다.

이벤트 리스너는 어떻게 작동하는가?

당신이 예상한 대로, 이벤트는 폴링을 통해 작동할 수 있습니다. 외부에서 발생하는 사건, 예를 들어 키보드 키가 눌리는 경우, 결국 폴링이 필요합니다.

하지만 모든 이벤트가 폴링을 필요로 하지는 않습니다. 예를 들어, 버튼 클릭 이벤트는 GUI 프레임워크가 마우스 클릭을 감지할 때 호출하는 메서드입니다. 이 경우, 마우스 클릭을 감지하기 위해 폴링이 필요하지만, 마우스 리스너는 폴링 메커니즘에 연결된 더 수동적인 요소입니다.

하드웨어에서의 저수준 폴링

USB 장치와 기타 현대 통신 프로토콜은 상당히 흥미로운 네트워킹과 유사한 프로토콜을 사용하여 I/O 장치와 통신합니다. "인터럽트"는 동기적인 중요한 작업으로, 임시적인 네트워크 토폴로지를 처리하지 않습니다. 이를 해결하기 위해 "인터럽트"는 비동기적인 고우선순위 패킷인 "인터럽트 트랜잭션" 또는 메시지 신호화된 인터럽트로 일반화되었습니다.

이 프로토콜은 USB 사양에서 설명되어 있습니다.

  • "Figure 8-31. Bulk/Control/Interrupt OUT Transaction Host State Machine" in "Universal Serial Bus Specification, Revision 2.0", printed-page-222; PDF-page-250 (2000-04-27)

요점은 I/O 장치와 통신 구성 요소(USB 허브 등)가 기본적으로 네트워크 장치처럼 작동한다는 것입니다. 따라서 메시지를 보내는데, 이를 위해 포트 등을 폴링해야 합니다. 이렇게 하면 전용 하드웨어 회선의 필요성이 줄어듭니다.

Windows와 같은 운영 체제는 폴링 프로세스 자체를 처리하는 것으로 보입니다. 예를 들어, MSDN documentation for the USB_ENDPOINT_DESCRIPTOR's 에 대한 설명대로 Windows가 인터럽트/동시적 메시지를 위해 USB 호스트 컨트롤러를 폴링하는 빈도를 제어하는 방법이 설명되어 있습니다.

bInterval 값은 인터럽트 및 동기식 엔드포인트의 폴링 간격을 나타냅니다. 다른 유형의 엔드포인트에는 이 값을 무시해야 합니다. 이 값은 장치의 펌웨어 구성에 반영됩니다. 드라이버는 이를 변경할 수 없습니다.
폴링 간격은 장치의 속도와 호스트 컨트롤러의 유형과 함께, 드라이버가 인터럽트나 동기식 전송을 얼마나 자주 시작할지 결정합니다. bInterval 값은 고정된 시간이 아니라 상대적인 값입니다. 실제 폴링 주기는 장치와 USB 호스트 컨트롤러가 저속, 전속도, 또는 고속 모드에서 작동하는지에 따라 달라질 수 있습니다.
"USB_ENDPOINT_DESCRIPTOR 구조", Hardware Dev Center, Microsoft

DisplayPort 와 같은 최신 모니터 연결 프로토콜도 동일한 작업을 수행하는 것으로 보입니다.

다중 스트림 전송(MST)
DisplayPort Ver.1.2에 MST(Multi-Stream Transport) 추가
Ver.1.1a에서는 SST(Single-Stream Transport)만 사용 가능
MST는 단일 커넥터를 통해 여러 A/V 스트림을 전송합니다.
최대 63개 스트림; "레인당 스트림" 아님
전송된 스트림 사이에 동기성이 가정되지 않음; 한 스트림은 블랭킹 기간에 있는 반면 다른 스트림은 그렇지 않을 수 있음
연결 지향 전송
스트림 전송이 시작되기 전에 AUX CH를 통한 메시지 트랜잭션을 통해 설정된 스트림 소스에서 대상 스트림 싱크까지의 경로
나머지 스트림에 영향을 주지 않고 스트림 추가/삭제

"DisplayPortTM Ver.1.2 개요" (2010-12-06) 의 슬라이드

이 추상화를 사용하면 하나의 연결에서 3개의 모니터를 실행하는 것과 같은 멋진 기능을 사용할 수 있습니다.

DisplayPort 멀티 스트림 전송도 3개 이상의 장치를 함께 연결할 수 있지만, 반대로 "소비자" 지향적이지 않은 구성으로, 단일 출력 포트에서 여러 디스플레이를 동시에 구동합니다.
Display 포트, 위키피디아

결론

개념적으로, 여기서 얻을 수 있는 요점은 폴링 메커니즘이 보다 일반화된 직렬 통신을 허용한다는 것입니다. 이는 보다 일반적인 기능을 원할 때 굉장합니다. 따라서 하드웨어와 OS는 논리적 시스템에 대해 많은 폴링을 수행합니다. 그런 다음 이벤트를 구독하는 소비자는 자체 폴링/메시지 전달 프로토콜을 작성하지 않고도 하위 레벨 시스템에서 해당 세부 정보를 처리하는 것을 즐길 수 있습니다.

결국 키 입력과 같은 이벤트는 소프트웨어 수준의 필수 이벤트 발생 메커니즘에 도달하기 전에 매우 흥미로운 일련의 이벤트를 거치는 것으로 보입니다.

출처: https://softwareengineering.stackexchange.com/a/363408

그러니까...

마우스, 키보드 장치 등외부 이벤트(External Events)Polling에 의존하고있다.
개발자가 작성한 로직인 프로그래밍 논리 이벤트(Programming logic-events)Polling에 의존하고 있지 않다.

결국 이벤트는 Interrupt가 아닌 Polling에 의존하고있다.
사실 Interrupt가 이벤트에 더 적합한 매커니즘 아닐까? 신호를 보내고, 신호를 받고...

이 또한 명쾌한 답은 아니다. USB와 DP에 관한 글은 명확한 출처가 존재하나, 이벤트에 관련된 글은 명확한 출처가 존재하지 않아 신뢰성이 떨어진다...


결론

전공자와 비전공자의 차이는 이런데서 나는 것 아닐까 싶다. 명확한 용어의 정의와 컴퓨터 과학적인 사고, 기반 지식들을 조립하여 명쾌한 해답을 끌어낼 수 없으니 답답할 따름이다...ㅠㅠ

당장 궁금증을 완벽히 해소하지는 못했지만, 어느정도 지식을 알고가는 선에서 타협하기로 했다.
나중에 전공자분들께 여쭤봐야지...

profile
모르는 것을 모른다고 하기

0개의 댓글