Polling
은 다른 장치의 상태를 주기적으로 검사한다는 의미다.
예를들어 HTTP통신에서 실시간 통신을 구현하는 방법중 하나가 있다.
setInterval(() => {
fetch(....);
}, 1000);
통신이 언제 발생할지 정확히 모르기 때문에 특정 주기마다 서버에 요청을 보낸다. 주체는 클라이언트이며 대상은서버다.
위처럼 소프트웨어 레벨의 폴링도 있고, 하드웨어 레벨의 폴링도 있다. I/O를 예로 들어보자.
USB
는 Polling
방식을 이용하여 CPU와의 입출력을 담당한다.
USB를 이용한 키보드(마우스등) 또한 Polling
방식을 이용한다.
이처럼 Polling
은 컴퓨터에 있어서 아주 기본적인 매커니즘이라고 할 수 있다.
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) |
---|---|---|
주체 | CPU가 상태를 확인 | 디바이스가 CPU에 신호를 보내며 CPU가 반응 |
작동 방식 | 주기적으로 상태를 확인 | 상태 변화가 발생했을 때만 신호를 받음 |
자원 소모 | 지속적으로 CPU 자원을 소모 | 상태 변화가 있을 때만 CPU 자원을 소모 |
효율성 | 비효율적 (상태 변화가 없어도 계속 확인) | 효율적 (변화가 있을 때만 반응) |
두 방식의 차이점을 간단히 요약해보았다.
Polling
은 주기적으로 상태를 체크한다.EventListener
는 특정한 이벤트가 발생할 시, trigger된다.Polling
하고 있다는 것 아닐까?이러한 사고의 흐름에 따라 이런 바보같은 생각이 들었다. 비전공자여서 그런지 명쾌한 해답이 바로 나오질 않았다.
그래서 열심히 찾아보니까 나와 같은 생각을 한 사람이 꽤 있었다!(바보들ㅎㅇ) 😮
이하 원문을 GPT로 돌려 번역한 내용을 요약해보았다.
소프트웨어 이벤트
큰 규모의 이벤트: 예를 들어, 쉘이 자식 프로세스의 종료를 기다리거나, 한 프로세스가 다른 프로세스의 메시지를 기다리는 경우. 이러한 이벤트는 반복적인 폴링(주기적인 확인)을 피하는 것이 좋습니다. 대신, 세마포어나 wait() 시스템 호출을 사용하여 대기 프로세스가 스스로 멈추고, 이벤트 발생 시 운영체제가 해당 프로세스를 깨워서 계속 실행하도록 합니다.
작은 규모의 이벤트: 멀티스레드 프로그램에서 스핀 락(spin lock)을 사용해 이벤트를 기다리기도 합니다. 스핀 락은 CPU 자원을 계속해서 소비하며 대기하는 방식입니다. 최신 CPU에서는 MONITOR/MWAIT 명령어로 대기 중에 저전력 상태로 들어가기도 하며, 속도가 중요한 경우 사용됩니다.
하드웨어 이벤트
인터럽트와 폴링의 혼합
결론 : 소프트웨어 이벤트는 주로 세마포어와 같은 구조를 통해 대기하며, 이는 폴링을 사용하지 않습니다. 하드웨어 이벤트는 인터럽트와 폴링 방식으로 처리됩니다. 각 방식은 상황에 따라 효율성을 최적화하기 위해 선택적으로 사용됩니다.
소프트웨어 이벤트는 세마포어 구조를 통해 대기한다. 이는 폴링을 사용하지 않는다. 다만, 작은 규모의 이벤트 (멀티스레드 프로그램)에서는 스핀 락이라는 폴링방식을 이용하여 대기하기도 한다.
궁금증이 조금 해소되었지만, 명쾌하진 않다.
이 정의들은 구현에 의존하지 않으므로, 다양한 방식으로 구현될 수 있습니다.
이 용어들 중 일부는 종종 동의어로 혼동되는데, 사용자가 이들 간의 차이를 구별할 필요가 없기 때문입니다.
다른 사람들이 지적한 점은, 폴링이 반드시 필요하지 않다는 것입니다. 이는 이벤트 발화가 자동으로 이벤트 핸들러를 호출하는 방식으로 구현될 수 있기 때문입니다. 시스템 수준의 이벤트일 경우, 이는 종종 가장 효율적인 방법입니다.
비유하자면, 만약 우체국 직원이 당신의 문을 두드려서 우편물을 직접 전달한다면, 매일 우편함을 확인할 필요가 없습니다.
하지만 이벤트 리스너는 폴링 방식으로도 작동할 수 있습니다. 폴링이 반드시 특정 값이나 다른 관찰 가능한 것들을 체크하는 것을 의미하지는 않지만, 기본적으로 폴링의 목적은 이벤트가 발생했을 때 이를 응답할 수 있도록 추론하는 것입니다.
비유하자면, 우체국 직원이 우편물을 우편함에 넣는다면 매일 우편함을 확인해야 할 것입니다. 하지만 우체국 직원에게 문을 두드리라고 지시할 수 있다면, 그럴 필요는 없겠죠. 다만, 그런 기능은 종종 제공되지 않습니다.
많은 프로그래밍 언어에서 키보드 키가 눌리거나 특정 시간이 될 때 이벤트를 처리할 수 있습니다. 이 경우 외부 이벤트지만, 폴링을 필요로 하지 않습니다. 왜냐하면 운영 체제가 대신 폴링을 하기 때문입니다. 예를 들어, 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는 논리적 시스템에 대해 많은 폴링을 수행합니다. 그런 다음 이벤트를 구독하는 소비자는 자체 폴링/메시지 전달 프로토콜을 작성하지 않고도 하위 레벨 시스템에서 해당 세부 정보를 처리하는 것을 즐길 수 있습니다.
결국 키 입력과 같은 이벤트는 소프트웨어 수준의 필수 이벤트 발생 메커니즘에 도달하기 전에 매우 흥미로운 일련의 이벤트를 거치는 것으로 보입니다.
마우스, 키보드 장치 등외부 이벤트(External Events)는 Polling
에 의존하고있다.
개발자가 작성한 로직인 프로그래밍 논리 이벤트(Programming logic-events)는 Polling
에 의존하고 있지 않다.
결국 이벤트는 Interrupt
가 아닌 Polling
에 의존하고있다.
사실 Interrupt
가 이벤트에 더 적합한 매커니즘 아닐까? 신호를 보내고, 신호를 받고...
이 또한 명쾌한 답은 아니다. USB와 DP에 관한 글은 명확한 출처가 존재하나, 이벤트에 관련된 글은 명확한 출처가 존재하지 않아 신뢰성이 떨어진다...
전공자와 비전공자의 차이는 이런데서 나는 것 아닐까 싶다. 명확한 용어의 정의와 컴퓨터 과학적인 사고, 기반 지식들을 조립하여 명쾌한 해답을 끌어낼 수 없으니 답답할 따름이다...ㅠㅠ
당장 궁금증을 완벽히 해소하지는 못했지만, 어느정도 지식을 알고가는 선에서 타협하기로 했다.
나중에 전공자분들께 여쭤봐야지...