이벤트 루프

Event loop

컴퓨터 과학에서 이벤트 루프는 프로그램 에서 이벤트나 메시지를 기다리고 디스패치하는 프로그래밍 구조 또는 설계 패턴입니다.이벤트 루프는 내부 또는 외부 '이벤트 프로바이더'(일반적으로 이벤트가 도착할 때까지 요구가 차단됨)에 요구를 한 후 관련 이벤트핸들러를 호출합니다("이벤트를 디스패치").이벤트 루프는 메시지디스패처, 메시지루프, 메시지펌프 또는 실행루프라고도 불립니다.

이벤트 루프는 이벤트 공급자가 파일인터페이스를 따를 경우 리액터와 함께 사용할 수 있습니다.파일 인터페이스는 선택 또는 폴링할 수 있습니다(실제 폴링이 아닌 Unix 시스템콜).이벤트 루프는 거의 항상 메시지 발신자와 비동기적으로 동작합니다.

이벤트 루프가 프로그램의 중앙 제어 흐름 구조를 형성하는 경우, 종종 그렇듯이, 메인 루프 또는 메인 이벤트 루프라고 불릴 수 있습니다.이러한 이벤트 루프는 프로그램 내에서 최고 수준의 제어에 있기 때문에 이 제목은 적절합니다.

메시지 전달

메시지 펌프는 프로그램 메시지 큐(일반적으로 기본 운영 체제에 의해 할당되고 소유됨)에서 프로그램으로 메시지를 '펌프'하여 처리한다고 합니다.가장 엄밀한 의미에서 이벤트 루프는 프로세스 간 통신을 구현하기 위한 방법 중 하나입니다.실제로 메시지 처리는 마하 운영 체제의 커널 수준 구성 요소를 포함하여 많은 시스템에 존재합니다.이벤트 루프는 메시지 전달을 사용하는 시스템의 특정 구현 기법입니다.

대체 설계

이 접근법은 다른 많은 대안과 대조적이다.

  • 기존에는 프로그램이 한 번만 실행되었다가 종료되었습니다.이러한 유형의 프로그램은 컴퓨팅 초기에는 매우 보편적이었으며 어떠한 형태의 사용자 인터랙티브도 결여되어 있었습니다.이는 특히 명령줄 기반 프로그램의 형태로 여전히 자주 사용됩니다.파라미터는 사전에 설정되며 프로그램 시작 시 한 번에 전달됩니다.
  • 메뉴 중심의 디자인.이것들은 여전히 메인루프를 특징으로 할 수 있지만, [citation needed]통상적인 의미에서 이벤트 구동이라고는 생각되지 않습니다.대신 수행하고자 하는 작업이 사용 가능한 유일한 옵션이 될 때까지 계속 좁혀지는 일련의 옵션이 사용자에게 표시됩니다.메뉴를 통한 제한된 인터랙티브를 사용할 수 있습니다.

사용.

그래픽 사용자 인터페이스가 우세하기 때문에 대부분의 최신 애플리케이션은 메인 루프를 특징으로 합니다.get_next_message()루틴은 일반적으로 운영 체제에서 제공되며 메시지를 사용할 수 있을 때까지 차단합니다.따라서 루프는 처리할 것이 있을 때만 입력됩니다.

메시지 != 종료 시 메시지 := get_next_message() process_message(message) 종료함수 main initialize()

파일 인터페이스

Unix에서는 "모든 것이 파일" 패러다임은 자연스럽게 파일 기반 이벤트 루프로 이어집니다.파일 읽기 및 쓰기, 프로세스 간 통신, 네트워크 통신 및 장치 제어는 모두 파일 I/O를 사용하여 수행되며 파일 설명자에 의해 대상이 식별됩니다.선택 폴링 시스템 호출을 통해 일련의 파일 기술자를 상태 변경(데이터를 읽을 수 있게 된 경우 등)에 대해 모니터링할 수 있습니다.

예를 들어 연속적으로 갱신된 파일로부터 읽어내, 그 내용을 X Window 시스템에 표시하는 프로그램을 생각해 봅시다.X Window System은 소켓(유닉스 도메인 또는 버클리)을 통해 클라이언트와 통신합니다.

방어하다 주된():     file_module = 열다.("logfile.log")     x_module = open_display(표시)()     construct_interface()     하는 동안에 진실의:         리스트, _, _ = 선택한다..선택한다.([file_module, x_module], [], []):         한다면 file_module  리스트:             데이터. = file_module.읽어주세요()             디스플레이에 추가(데이터.)             send_repaint_message()         한다면 x_module  리스트:             프로세스_x_module() 

신호 처리

UNIX에서 파일인터페이스에 준거하지 않는 몇 안 되는 것 중 하나가 비동기 이벤트(신호)입니다.시그널 핸들러로 신호가 수신됩니다.이러한 코드는 나머지 태스크가 정지되어 있는 동안 실행됩니다.태스크가 차단되어 있는 동안 신호가 수신되어 처리되는 경우select()를 선택하면 EINTR이 조기에 반환됩니다.작업이 CPU 바인딩되어 있는 동안 신호가 수신되면 신호 핸들러가 반환될 때까지 작업은 명령 간에 일시 중단됩니다.

따라서 신호를 처리하는 명확한 방법은 신호 핸들러가 글로벌플래그를 설정하고 이벤트루프가 플래그의 직전과 직후에 플래그를 체크하는 것입니다.select()call: 설정되어 있는 경우는, 파일 기술자의 이벤트와 같은 방법으로 신호를 처리합니다.안타깝게도 이는 레이스 상태를 야기한다: 깃발 확인과 호출 사이에 신호가 즉시 도착할 경우select()~까지 처리되지 않습니다.select()다른 이유(예를 들어 사용자가 방해한 경우)가 반환됩니다.

POSIX가 도달한 솔루션은pselect()call, 와 유사합니다.select()단, 추가가 필요합니다.sigmask파라미터 - 신호 마스크에 대해 설명합니다.이를 통해 응용 프로그램은 주요 작업에서 신호를 마스킹한 다음 마스크 제거 작업을 수행하는 동안select()응용 프로그램이 I/O바운드되어 있을 때만 신호 핸들러가 호출되도록 호출합니다.단, 의 실장pselect()항상 신뢰할 수 있는 것은 아닙니다.Linux 2.6.16 이전 버전에는pselect()시스템 콜,[1] glibc가 동일한 레이스 조건이 발생하기 쉬운 메서드를 통해 에뮬레이트하도록 강제한다.pselect()회피하기 위한 것입니다.

보다 휴대성이 뛰어난 대체 솔루션은 셀프 파이프 [2]트릭을 사용하여 비동기 이벤트를 파일 기반 이벤트로 변환하는 것입니다.여기서 신호 핸들러는 다른 한쪽 끝을 감시하는 파이프에 바이트를 씁니다.select()메인 프로그램에서"[3]라고 적혀있습니다.Linux 커널 버전 2.6.22에서는 새로운 시스템콜이signalfd()특별한 파일 기술자를 통해 신호를 수신할 수 있는 기능이 추가되었습니다.

실장

Windows 응용 프로그램

Microsoft Windows operating system에서는, 유저와 대화하는 프로세스는, 착신 메세지를 받아 들여 응답할 필요가 있습니다.이것은, 거의 필연적으로, 그 프로세스에서의 메시지루프에 의해서 행해집니다.Windows 에서는, 메세지는, operating system에 작성되어 부과되는 이벤트와 같습니다.이벤트는 사용자 상호작용, 네트워크 트래픽, 시스템 처리, 타이머 액티비티, 프로세스 간 통신 등이 될 수 있습니다.비인터랙티브 I/O 전용 이벤트의 경우 Windows에는 I/O 완료 포트가 있습니다.I/O 완료 포트 루프는 메시지루프와는 별도로 실행되며 개봉 후 메시지루프와 상호 작용하지 않습니다.

대부분의 Win32 어플리케이션의 "하트"는 루프에서 GetMessage()를 호출하는 WinMain() 함수입니다.GetMessage()는 메시지 또는 "이벤트"가 수신될 때까지 차단합니다(비블로킹 대체 기능으로 PeekMessage() 함).옵션 처리 후 Dispatch Message()호출하여 메시지를 관련 핸들러(일명 Window Proc)로 디스패치합니다.보통 특별한 WindowProc()가 없는 메시지는 기본 메시지인 DefWindowProc로 발송됩니다.Dispatch Message()는 Register Class() 함수에 등록된 메시지의 HWND 핸들의 Window Proc를 호출합니다.

메시지 순서

최신 버전의 Microsoft Windows 에서는, 메세지가 시스템이나 주변기기에 의해서 인식된 순서대로, 애플리케이션의 메시지 루프에 전달되는 것을 프로그래머에게 보증합니다.이 보증은 멀티스레드 애플리케이션의 설계 결과를 고려할 때 필수적입니다.

단, 항상 마지막으로 수신되는 메시지나 문서화된 [4]우선순위가 다른 메시지 등 일부 메시지에는 다른 규칙이 있습니다.

X 윈도 시스템

Xlib 이벤트루프

Xlib를 직접 사용하는 X개의 애플리케이션은 다음과 같이 구축되어 있습니다.XNextEvent기능 패밀리XNextEvent는 이벤트 큐에 이벤트가 표시될 때까지 차단합니다.이것에 의해, 애플리케이션은 이벤트를 적절히 처리합니다.Xlib 이벤트루프는 윈도 시스템이벤트만 처리합니다.다른 파일이나 디바이스에서 대기할 필요가 있는 어플리케이션은 다음과 같은 프리미티브에서 독자적인 이벤트루프를 구축할 수 있습니다.ConnectionNumber그러나 실제로는 멀티스레딩을 사용하는 경향이 있습니다.

Xlib를 직접 사용하는 프로그램은 거의 없습니다.보다 일반적인 경우 Xlib 기반의 GUI 툴킷은 보통 이벤트 추가를 지원합니다.를 들어 XtIntentics 기반의 툴킷에는XtAppAddInput()그리고.XtAppAddTimeout().

신호 핸들러에서 Xlib 함수를 호출하는 것은 안전하지 않습니다.X 어플리케이션이 임의의 상태(예: 내부)에서 중단되었을 수 있기 때문입니다.XNextEventX11R5, X11R6 및 Xt용 솔루션에 대해서는 [1]을 참조하십시오.

GLIB 이벤트루프

GLib 이벤트루프는 원래 GTK에서 사용하기 위해 작성되었지만 현재는 D-Bus 등 GUI 이외의 애플리케이션에서도 사용되고 있습니다.폴링되는 리소스는 응용 프로그램이 관여하는 파일 기술자의 집합입니다.신호가 도착하거나 타임아웃이 만료되면(예를 들어 응용 프로그램이 타임아웃 또는 아이돌태스크를 지정한 경우) 폴링 블록이 중단됩니다.GLib에는 파일 기술자 및 자식 종료 이벤트에 대한 지원이 포함되어 있지만, prepare-check-dispatch 모델에서 처리할 수 있는 모든 이벤트에 대해 이벤트 소스를 추가할 수 있습니다.[2]

GLib 이벤트 루프를 기반으로 구축된 애플리케이션 라이브러리에는 GStreamerGnome비동기 I/O 메서드가 포함됩니다.VFS는 GTK가 가장 눈에 띄는 클라이언트라이브러리로 남습니다윈도우 시스템으로부터의 이벤트(X에서 X 소켓에서 읽기)는 GDK에 의해 GTK 이벤트로 변환되어 애플리케이션의 위젯 개체에서 GLib 신호로 출력됩니다.

macOS Core Foundation 실행 루프

스레드당 정확히 1개의 CFRunLoop이 허용되며 임의로 많은 소스 및 옵서버를 연결할 수 있습니다.그런 다음 소스는 실행 루프를 통해 옵서버와 통신하고 메시지 큐잉 및 디스패치를 구성합니다.

CFRunLoop은 Cocoa에서 NSRunLoop으로 추상화되며, 이를 통해 (비반사 런타임의 함수 호출과 동일) 모든 메시지를 큐잉하여 모든 물체에 발송할 수 있습니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ "Linux_2_6_16 - Linux Kernel Newbies". kernelnewbies.org. Retrieved 2021-03-03.
  2. ^ D. J. Bernstein. "The self-pipe trick".
  3. ^ BUGS, : 동기 I/O 다중화– Linux 프로그래머 매뉴얼– 시스템콜
  4. ^ 메시지 priority 목록을 가진 GetMessage() 함수.

외부 링크