비동기 I/O

Asynchronous I/O

컴퓨터 과학에서 비동기 I/O(비순차 I/O)는 전송이 완료되기 전에 다른 처리를 계속할 수 있도록 하는 입출력 처리의 한 형태입니다.윈도우즈 API에서 비동기 I/O에 사용되는 이름이 겹칩니다.

컴퓨터의 입출력(I/O) 작업은 데이터 처리에 비해 매우 느릴 수 있습니다.I/O 장치에는 읽기 또는 쓰기 트랙을 찾는 하드 드라이브와 같이 물리적으로 이동해야 하는 기계 장치가 포함될 수 있습니다. 이는 종종 전류 전환보다 훨씬 느립니다.예를 들어 디스크 동작에 10밀리초가 걸리는 동안 1기가헤르츠로 클럭된 프로세서는 1,000만 개의 명령 처리 사이클을 수행할 수 있었습니다.

I/O에 대한 간단한 접근법은 액세스를 시작한 후 완료될 때까지 기다리는 것입니다.그러나 이러한 접근법(동기 I/O 또는 블로킹 I/O라고 함)은 통신 중에 프로그램의 진행을 차단하여 시스템 리소스를 유휴 상태로 만듭니다.프로그램이 많은 I/O 조작을 실시하는 경우(예를 들면, 프로그램 등, 주로 유저의 입력에 의존하고 있는 경우)는, 프로세서가 I/O 조작의 완료를 기다리는 동안, 거의 모든 시간을 아이돌 상태로 보낼 수 있는 것을 의미합니다.

또, 통신을 개시해, I/O를 완료할 필요가 없는 처리를 실행할 수도 있습니다.이 방식을 비동기 입출력이라고 합니다.완료된 I/O에 의존하는 작업(입력값과 쓰기 작업이 완료되었음을 보증하는 중요한 작업 모두 포함)은 I/O 작업이 완료될 때까지 기다려야 하므로 차단되지만 I/O 작업에 의존하지 않는 다른 처리는 계속할 수 있습니다..

많은 운영 체제 기능이 다양한 수준에서 비동기 I/O를 구현합니다.사실 운영체제의 가장 기초적인 기능 중 하나는 사용자나 프로그래머에게는 특별히 눈에 띄지 않을 수 있지만 적어도 어떤 형태의 기본적인 비동기 I/O를 실행하는 것입니다.가장 간단한 소프트웨어 솔루션에서는 하드웨어 디바이스 상태가 정기적으로 폴링되어 디바이스가 다음 동작에 대응할 준비가 되어 있는지 여부를 검출합니다.(예를 들어 CP/M 운영체제는 이렇게 구축되어 있습니다).대부분의 구현이 더 복잡하고 효율적이긴 했지만, 시스템 호출 의미론에는 이보다 더 정교한 I/O 구조가 필요하지 않았습니다.)Direct Memory Access(DMA; 다이렉트메모리 액세스)에 의해 폴링 베이스의 시스템의 효율이 큰폭으로 향상해, 하드웨어의 인터럽트에 의해서 폴링이 불필요하게 됩니다.멀티태스킹 운영체제는 하드웨어 인터럽트에 의해 제공되는 기능을 이용하면서 인터럽트 처리의 복잡성을 사용자에게 숨길 수 있습니다.스풀링은 비동기 I/O를 이용하기 위해 설계된 최초의 멀티태스킹 형태 중 하나입니다.마지막으로, 사용자 프로세스 의 멀티스레딩 및 명시적인 비동기 I/O API는 소프트웨어의 복잡성을 증가시키면서 비동기 I/O를 더욱 이용할 수 있습니다.

비동기 I/O는 에너지 효율 및 경우에 따라서는 throughput을 향상시키기 위해 사용됩니다.그러나 경우에 따라 지연 시간 및 처리량에 부정적인 영향을 미칠 수 있습니다.

I/O의 형태 및 POSIX 기능의 예:

막는 논블로킹 비동기
API 쓰기, 읽기 쓰기, 읽기 + 폴링 / 선택 aio_write, aio_read

모든 형태의 비동기 I/O는 잠재적인 리소스 충돌 및 관련 장애까지 애플리케이션을 엽니다.이를 방지하려면 주의 깊은 프로그래밍(상호 제외, 세마포어 사용 등)이 필요합니다.

애플리케이션에 비동기 I/O를 노출하는 경우 몇 가지 광범위한 구현 클래스가 있습니다.응용 프로그램에 제공되는 API의 형식이 운영 체제에서 실제로 제공되는 메커니즘과 반드시 일치하는 것은 아닙니다. 에뮬레이션이 가능합니다.게다가 1개의 애플리케이션에서는, 그 요구와 프로그래머의 요망에 따라서, 복수의 방법을 사용할 수 있다.많은 운영체제가 이러한 메커니즘을 여러 개 제공하고 있으며, 일부 운영체제는 이러한 메커니즘을 모두 제공할 수 있습니다.

과정

초기 Unix에서 사용 가능.멀티태스킹 운영체제에서는 프로세싱을 여러 프로세스로 분산할 수 있습니다.프로세스는 독립적으로 실행되며 자체 메모리가 있으며 자체 I/O 플로우를 처리합니다.이러한 플로우는 일반적으로 파이프라인으로 연결됩니다.프로세스 작성 및 [citation needed]유지보수에 비용이 많이 들기 때문에 이 솔루션은 일련의 프로세스가 작고 비교적 안정적인 경우에만 잘 작동합니다.또한 개별 프로세스가 서로의 I/O 처리와는 별도로 독립적으로 작동할 수 있다고 가정합니다. 다른 방식으로 통신할 필요가 있는 경우에는 프로세스를 조정하는 것이 [citation needed]어려울 수 있습니다.

이 접근방식의 확장으로는 데이터 플로우프로그래밍이 있습니다이것에 의해, 파이프가 서포트하는 체인보다 복잡한 네트워크가 가능하게 됩니다.

폴링

종류:

  • 아직 할 수 없는 경우 오류 발생(나중에 재발행)
  • 차단하지 않고 실행할 수 있는 타이밍을 보고한다(그 후 발행한다.

폴링은 비동기 API를 구현하기 위해 사용할 수 있는 논블로킹 동기 API를 제공합니다.기존 Unix 및 Windows에서 사용할 수 있습니다.그 주된 문제는 발행 프로세스가 할 수 있는 다른 작업이 없을 때 반복적으로 CPU 폴링 시간을 낭비하여 다른 프로세스에 사용할 수 있는 시간을 단축할 수 있다는 것입니다.또, 폴링 애플리케이션은 기본적으로 싱글 스레드이기 때문에, 하드웨어에 대응한 I/O 병렬 처리를 완전하게 이용하지 못할 가능성이 있습니다.

선택(/poll) 루프

BSD Nix 및 BSD 구현을 이용하거나 BSD 구현을 본뜬 TCP/IP 프로토콜 스택과 함께 사용할 수 있습니다.폴링 테마의 변화입니다.선택 루프는select파일 기술자에서 조건이 발생할 때까지(예: 데이터를 읽을 수 있는 경우), 시간 초과가 발생하거나 신호가 수신될 때까지(예: 하위 프로세스가 종료될 때) sleep 상태로 시스템 호출을 호출합니다.의 반환 파라미터를 조사함으로써selectcall, 루프는 변경된 파일 기술자를 검색하여 적절한 코드를 실행합니다.대부분의 경우 사용하기 쉽도록 선택 루프는 이벤트루프로서 구현됩니다.콜백 함수를 사용하여 구현됩니다.이 상황은 이벤트 구동 프로그래밍에 특히 적합합니다.

이 방법은 신뢰성이 높고 비교적 효율적이지만 "모든 것이 파일"이라는 Unix 패러다임에 크게 의존합니다.파일 기술자가 포함되지 않은 블로킹 I/O는 프로세스를 차단합니다.선택 루프는 중앙의 모든 I/O를 포함할 수 있어야 합니다.selectcall; 자체 I/O를 실행하는 라이브러리는 이 점에서 특히 문제가 있습니다.또 다른 잠재적인 문제는 셀렉트와 I/O 조작이 아직 충분히 분리되어 있기 때문에 셀렉트의 결과는 사실상 거짓일 수 있다는 것입니다.두 프로세스가 하나의 파일 기술자(아마도 잘못된 설계)에서 읽었을 경우, 셀렉트는 판독이 발행될 때까지 사라진 읽기 데이터의 가용성을 나타낼 수 있습니다.블로킹이 발생합니다.2개의 프로세스가 1개의 파일 기술자에 기입하고 있는 경우(그렇게 드물지 않은 경우), 선택은 즉시 기입 가능 여부를 나타내지만, 기입은 여전히 블록될 수 있습니다.이는 버퍼가 중간에 다른 프로세스에 의해 채워졌거나 사용 가능한 버퍼에 대해 쓰기가 너무 크기 때문이거나 기타 방법으로 수신에 적합하지 않기 때문입니다.펜트

예를 들어 complete queues 메서드에서는 select loop이 가능한 궁극의 시스템 효율에 도달하지 않습니다.이는 complete queues 메서드의 의미이기 때문입니다.select콜은 허용 가능한 이벤트세트의 콜 단위 튜닝과 마찬가지로 선택 배열을 통과하는 호출마다 어느 정도의 시간을 소비합니다.로 인해 윈도 시스템용 파일 기술자가1개, 오픈 파일이 몇 개 있는 사용자 애플리케이션에는 오버헤드가 거의 발생하지 않지만 잠재적인 이벤트 소스의 수가 증가함에 따라 문제가 더욱 커지며 C10k 문제처럼 다수의 클라이언트서버 애플리케이션 개발을 방해할 수 있습니다.다른 비동기 방식도 눈에 띌 수 있습니다.그런 경우에는 더 효율적입니다.일부 Unix에서는 시스템 고유의 콜을 확장성이 뛰어난 콜을 제공하고 있습니다.예를 들어 다음과 같습니다.epollLinux의 경우(반환 선택 배열에 이벤트가 발생한 이벤트 소스만 포함),kqueueFreeBSD이벤트 포트(및/dev/poll)를 참조해 주세요.

SVR3Unix는 다음을 제공했습니다.poll시스템 콜을 실행합니다.거의 틀림없이 더 좋은 이름일 것이다select, 이 논의의 목적상, 그것은 본질적으로 같은 것입니다.SVR4 Unix( POSIX)는 양쪽 콜을 제공합니다.

신호(인터럽트)

BSDPOSIX Unix에서 사용할 수 있습니다.I/O는 비동기적으로 발행되며, 이것이 완료되면 신호(인터럽트)가 발생한다.저레벨 커널 프로그래밍과 마찬가지로 신호 핸들러 내에서 안전하게 사용할 수 있는 설비는 제한되며 프로세스의 주요 흐름은 거의 모든 지점에서 중단되어 신호 핸들러에서 볼 수 있는 데이터 구조의 불일치가 발생할 수 있습니다.일반적으로 신호 핸들러는 그 자체로는 더 이상의 비동기 I/O를 발행할 수 없습니다.

시그널 어프로치는, OS내에서 비교적 간단하게 실장할 수 있지만, operating system의 커널 인터럽트 시스템 작성에 수반하는 불쾌한 부하를 애플리케이션 프로그램에 가져옵니다.최악의 특징은 모든 블로킹(동기) 시스템콜이 중단될 가능성이 있다는 입니다.일반적으로 프로그래머는 [citation needed]콜마다 리트라이 코드를 포함해야 합니다.

콜백 함수

기존의 Mac OS, VMSWindows에서 사용 가능.신호 방식은 기본적으로 동일하지만 거의 인식되지 않기 때문에 신호 방식의 많은 특성을 가지고 있습니다.차이점은 일반적으로 각 I/O 요청에는 자체 완료 기능이 있는 반면 신호 시스템에는 단일 콜백이 있다는 것입니다.

한편, 콜백을 사용하는 경우의 잠재적인 문제는 스택의 깊이가 관리 불능이 될 수 있다는 것입니다.이는 I/O가 종료되었을 때 다른 I/O를 스케줄 하는 것이 매우 일반적이기 때문입니다.이것이 즉시 충족되어야 할 경우 첫 번째 콜백은 다음 콜백이 호출되기 전에 스택에서 "unwound"되지 않습니다.이를 방지하기 위한 시스템(예: 새로운 작업의 '미드레인지' 스케줄링)은 복잡성을 가중시키고 성능을 저하시킵니다.그러나 일반적으로 새로운 I/O가 시작되면 즉시 새로운 I/O 자체가 반환되므로 실제로는 문제가 되지 않습니다.이 문제는 첫 번째 콜백이 반환될 때까지 큐를 사용하여 콜백을 회피하는 것으로도 방지할 수 있습니다.

경량 프로세스 또는 스레드

Light-Weight Process(LWP; 경량 프로세스) 또는 스레드는 Plan [citation needed]9에서 유래한 보다 현대적인 Unix에서 사용할 수 있습니다.프로세스 방식과 마찬가지로 흐름의 조정을 방해하는 데이터 격리는 없습니다.이러한 분리 부족으로 인해 자체 문제가 발생하며, 일반적으로 커널에서 제공하는 동기화 메커니즘과 스레드 세이프 라이브러리가 필요합니다.각 LWP 또는 스레드 자체는 기존의 차단 동기 I/O를 사용합니다.필요한 개별 스레드별 스택으로 인해 매우 많은 수의 스레드를 사용하는 대규모 구현이 방해될 수 있습니다.텍스트(코드) 흐름과 시각(이벤트) 흐름의 분리는 오류의 비옥한 토대를 제공합니다.

이 접근법은 Erlang 프로그래밍 언어 런타임 시스템에서도 사용됩니다.Erlang 가상 머신은 몇 개의 스레드 또는 경우에 따라서는 하나의 프로세스로 구성된 작은 풀을 사용하여 최대 수백만 개의 Erlang 프로세스에서 발생하는 I/O를 처리합니다.각 프로세스의 I/O 처리는 대부분 동기식 I/O 블로킹을 사용하여 작성됩니다.이와 같이 비동기식 I/O의 고성능과 일반 I/O의 단순성(c.f. Actor 모델)이 결합됩니다.Erlang의 많은 I/O 문제는 메시지 전달에 매핑되며, 메시지 전달은 내장된 선택적 수신을 사용하여 쉽게 처리할 수 있습니다.

파이버/코루틴은 Erlang 런타임 시스템 외부에서 비동기 I/O를 수행하는 것과 유사한 경량 접근법으로 볼 수 있지만 Erlang 프로세스와 동일한 보증을 제공하지는 않습니다.

완료 큐/포트

Microsoft Windows, Solaris, AmigaOS, DNIXLinux에서 이용 가능 (io_uring 사용, 5.1 [1]이상에서 이용 가능)I/O 요청은 비동기적으로 발행되지만 완료 알림은 완료 순서대로 동기화 큐 메커니즘을 통해 제공됩니다.통상, 메인 프로세스의 스테이트 머신 구조화(이벤트 드리븐 프로그래밍)와 관련지어져 있습니다.이는 비동기 I/O를 사용하지 않는 프로세스나 다른 형식 중 하나인 방해 코드 재사용과[citation needed] 거의 유사하지 않습니다.추가 특수 동기화 메커니즘이나 스레드 세이프 라이브러리가 필요하지 않으며 텍스트(코드) 흐름과 시간(이벤트) 흐름이 분리되지 않습니다.

이벤트 플래그

VMS 및 Amiga에서 사용 가능OS(종종 완료 포트와 함께 사용).완료 큐 방식은 기본적으로 깊이 1의 완료 큐이기 때문에 완료 큐 방식의 많은 특성을 가집니다.대기열 '깊이'의 효과를 시뮬레이션하려면 처리되지 않은(그러나 완료된) 각 잠재적인 이벤트에 대해 추가 이벤트 플래그가 필요합니다. 그렇지 않으면 이벤트 정보가 손실될 수 있습니다.이러한 클러스터 내에서 사용 가능한 다음 이벤트를 대기하려면 더 많은 수의 병렬 이벤트까지 확장되지 않을 수 있는 동기화 메커니즘이 필요합니다.

채널 I/O

IBM, Groupe Bull 및 Unisys에서 메인프레임으로 제공됩니다.채널 I/O는 대부분의 I/O를 코프로세서에 오프로드하여 CPU 사용률과 throughput을 최대화할 수 있도록 설계되었습니다.코프로세서는 온보드 DMA를 탑재하고 디바이스 인터럽트를 처리하며 메인 CPU에 의해 제어되며 메인 CPU는 꼭 필요할 때만 인터럽트됩니다.또한 이 아키텍처는 채널 프로세서에서 실행되는 소위 채널 프로그램을 지원하여 I/O 작업 및 프로토콜을 위해 많은 작업을 수행합니다.

등록 I/O

Windows Server 2012 및 Windows 8에서 사용할 수 있습니다.대량의 작은 메시지를 처리하는 애플리케이션에 최적화되어 지터와 [2]레이텐시를 줄이고 초당 높은 I/O 처리를 실현합니다.

실행

범용 컴퓨팅 하드웨어의 대부분은 전적으로 비동기 I/O 구현 방법인 폴링과 인터럽트에 의존합니다.보통 두 가지 방법이 함께 사용됩니다. 균형은 하드웨어의 설계와 필요한 성능 특성에 크게 좌우됩니다(DMA 자체는 또 다른 독립된 방법이 아니며 폴링 또는 인터럽트당 더 많은 작업을 수행할 수 있는 수단일 뿐입니다).

폴링 시스템은 완전히 가능합니다.소형 마이크로 컨트롤러(예를 들어 PIC를 사용하는 시스템)는 종종 이러한 방식으로 구축됩니다.CP/M 시스템도 DMA 유무에 관계없이 구축될 수 있습니다.또한 일부 태스크에만 최고의 퍼포먼스가 필요한 경우에는 다른 잠재적인 태스크를 희생하여 폴링할 수도 있습니다.방해를 받는 데 드는 부담이 달갑지 않을 수도 있기 때문에 격분하고 있다.(인터럽트를 처리하려면 중단된 작업을 재개하는 데 필요한 시간과 함께 프로세서 상태의 적어도 일부를 절약하기 위한 시간(및 공간)이 필요합니다).

대부분의 범용 컴퓨팅 시스템은 인터럽트에 크게 의존하고 있습니다.일반적으로 폴링의 일부 컴포넌트도 필요하지만, 폴링은 복수의 인터럽트 잠재적인 소스가 공통 인터럽트 신호선을 공유하는 것이 매우 일반적이기 때문에 가능한 경우가 있습니다.이 경우 폴링은 실제 소스를 해결하기 위해 디바이스 드라이버 내에서 사용됩니다.(이 해결 시간은 인터럽트 시스템의 성능 저하에도 기여합니다.수년간 인터럽트 서비스 관련 오버헤드를 최소화하기 위해 많은 작업이 수행되었습니다.현재의 인터럽트 시스템은 고도로 조정된 이전 시스템에 비해 다소 무디지만 하드웨어 성능이 전반적으로 향상됨에 따라 이 점이 크게 완화되었습니다.)

하이브리드 어프로치도 가능합니다.인터럽트는 비동기 I/O의 일부 버스트 시작을 트리거할 수 있으며 폴링은 버스트 자체 내에서 사용됩니다.이 기술은 네트워크나 디스크 등의 고속 디바이스 드라이버에서 흔히 볼 수 있습니다.이러한 드라이버에서는 인터럽트 전 태스크로 돌아가기 위한 시간이 다음에 필요한 서비스까지의 시간보다 길어집니다.(현재 사용되는 일반적인 I/O하드웨어는 DMA 및 대용량 데이터 버퍼에 의해 비교적 퍼포먼스가 낮은 인터럽트 시스템을 보완합니다.이러한 기능은 드라이버 루프 내에서 폴링을 사용하여 스루풋이 대폭 향상될 수 있습니다.데이터 단위의 폴링은 항상 성공하거나 최대 몇 번 반복하는 것이 이상적입니다).

DMA나 큰 버퍼링이 없는 디스크 및 네트워크 드라이버에서는 한때 이러한 하이브리드 방식이 일반적이었습니다.필요한 전송 속도는 데이터당 최소 4개의 동작(비트 테스트, 조건부 브랜치 투 셀프, 가져오기 및 저장)을 허용하는 속도보다 빠르기 때문에 하드웨어는 I/O 디바이스에서 자동 대기 상태 생성으로 구축되어 데이터 준비 폴링을 소프트웨어에서 밀어내고 프로세서의 가져오기 또는 저장 ha로 밀어냅니다.프로그래밍된 루프를 두 번의 작업으로 줄입니다.(실제로 프로세서 자체를 DMA 엔진으로 사용합니다).6502 프로세서는 하드웨어 핀을 탑재하고 있기 때문에 데이터당 3 엘리먼트 루프를 제공하는 이례적인 수단이 되었습니다.이 핀은 프로세서의 오버플로 비트를 직접 설정할 수 있습니다.(디바이스 드라이버 외부의 오버플로 비트를 오버플로하지 않도록 하드웨어 설계에 매우 주의를 기울여야 합니다.)

합성

위의 두 가지 도구(폴링 및 인터럽트)만 사용하여 위에서 설명한 다른 모든 형태의 비동기 I/O를 합성할 수 있습니다.

Java Virtual Machine(JVM; Java 가상 머신)과 같은 환경에서는 JVM이 실행 중인 환경에서는 비동기 I/O가 전혀 제공되지 않더라도 비동기 I/O를 합성할 수 있습니다.이는 JVM의 해석된 특성 때문입니다.JVM은 제어 변경의 내부 흐름을 정기적으로 폴링(또는 인터럽트)하여 여러 프로세스의 외관에 영향을 줄 수 있으며, 이들 중 적어도 일부는 비동기 I/O를 수행하기 위해 존재할 수 있습니다.(물론 미시적 수준에서는 병렬화가 다소 거칠고 이상적이지 않은 특성을 나타낼 수 있습니다.)하지만 표면적으로는 원하는 것처럼 보일 것입니다.)

실제로 폴링을 사용하여 다른 형태의 비동기 I/O를 합성할 경우 문제가 발생합니다.폴링된 모든 CPU 사이클은 낭비되고 원하는 작업을 수행하는 대신 오버헤드로 손실됩니다.폴링이 아닌 모든 CPU 주기는 보류 중인 I/O에 대한 응답 지연 시간이 증가했음을 나타냅니다.이 두 대립하는 힘 사이에서 허용 가능한 균형을 잡는 것은 어렵습니다(이것이 하드웨어 인터럽트 시스템이 애초에 발명된 이유입니다).

효율을 최대화하는 비결은 인터럽트 수신 시 수행해야 하는 작업량을 최소화하여 적절한 애플리케이션을 깨우는 것입니다.두 번째로 (그러나 마찬가지로 중요한 것은) 어플리케이션 자체가 무엇을 해야 하는지를 결정하기 위해 사용하는 방법입니다.

특히 문제가 되는 것은 (애플리케이션의 효율화를 위해서) 선택/폴링 메커니즘을 포함한 노출된 폴링 방법입니다.관심 있는 기본 I/O 이벤트는 인터럽트 기반일 가능성이 높지만 이 메커니즘에 대한 상호작용이 폴링되고 폴링에 많은 시간이 소요될 수 있습니다.이는 선택(및 폴링)을 통해 잠재적으로 대규모 폴링이 가능한 경우에 특히 해당됩니다.인터럽트는 Signals, Callback 함수, Completion Queues 및 Event 플래그에 매우 잘 매핑됩니다.이러한 시스템은 매우 효율적입니다.

다음 예시는 읽기 작업에 대한 세 가지 I/O 접근 방식의 개념을 보여 줍니다.객체 및 함수는 추상적입니다.

1. 블로킹, 동기:

장치 = 입출력.열다.() 데이터. = 장치.읽어주세요() # 스레드는 디바이스에 데이터가 있을 때까지 차단됩니다. 인쇄물(데이터.) 

2. 블로킹과 비블로킹, 동기: (여기서)IO.poll()최대 5초 동안 차단합니다만,device.read()하지 않다)

장치 = 입출력.열다.() 준비가 되어 있습니다! = 거짓의 하는 동안에 것은 아니다. 준비가 되어 있습니다!:     인쇄물("읽을 데이터가 없습니다!")     준비가 되어 있습니다! = 입출력.여론 조사(장치, 입출력.입력, 5) #는 5초가 경과했거나 읽을 데이터가 있는 경우 제어를 반환합니다(INPUT). 데이터. = 장치.읽어주세요() 인쇄물(데이터.) 

3. 비블로킹, 비동기:

IOS = 입출력.IOS 서비스() 장치 = 입출력.열다.(IOS)  방어하다 입력 핸들러(데이터., 에러):     "입력 데이터 핸들러"     한다면 것은 아니다. 에러:         인쇄물(데이터.)  장치.읽기(입력 핸들러) IOS.고리() # 모든 작업이 완료될 때까지 기다렸다가 모든 적절한 핸들러를 호출합니다. 

다음은 Async/ait와 같은 예입니다.

IOS = 입출력.IOS 서비스() 장치 = 입출력.열다.(IOS)  비동기 방어하다 작업():     해라:          데이터. = 기다리다 장치.읽기()         인쇄물(데이터.)     제외하고:         통과하다  IOS.태스크 추가(작업) IOS.고리() # 모든 작업이 완료될 때까지 기다렸다가 모든 적절한 핸들러를 호출합니다. 

Reactor 패턴의 예를 다음에 나타냅니다.

장치 = 입출력.열다.() 리액터 = 입출력.리액터()  방어하다 입력 핸들러(데이터.):     "입력 데이터 핸들러"     인쇄물(데이터.)     리액터.이제 그만()  리액터.add 핸들러(입력 핸들러, 장치, 입출력.입력) 리액터.달려.() # run reactor: 이벤트를 처리하고 적절한 핸들러를 호출합니다. 

「 」를 참조해 주세요.

레퍼런스

  1. ^ Corbet, Jonathan. "Ringing in a new asynchronous I/O API". LWN.net. Retrieved 27 July 2020.
  2. ^ "Registered Input-Output (RIO) API Extensions". technet.microsoft.com.

외부 링크