동기화 및 겹치는 입력 및 출력

파일, 명명된 파이프 및 직렬 통신 디바이스에서 동기 또는 비동기(겹침이라고도 함) I/O 작업을 수행할 수 있습니다. WriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipeTransactNamedPipe 함수는 동기 또는 비동기적으로 수행할 수 있습니다. ReadFileExWriteFileEx 함수는 비동기적으로만 수행할 수 있습니다.

함수가 동기적으로 실행되면 작업이 완료될 때까지 반환되지 않습니다. 즉, 시간이 많이 걸리는 작업이 완료될 때까지 기다리는 동안 호출 스레드의 실행을 무기한 차단할 수 있습니다. 작업이 완료되지 않았더라도 겹치는 작업에 대해 호출된 함수는 즉시 반환될 수 있습니다. 이렇게 하면 호출 스레드가 다른 작업을 자유롭게 수행할 수 있는 동안 백그라운드에서 시간이 많이 걸리는 I/O 작업을 실행할 수 있습니다. 예를 들어 단일 스레드는 다른 핸들에서 동시 I/O 작업을 수행하거나 동일한 핸들에서 동시 읽기 및 쓰기 작업을 수행할 수 있습니다.

겹치는 작업의 완료와 실행을 동기화하기 위해 호출 스레드는 GetOverlappedResult 함수, GetOverlappedResultEx 함수 또는 대기 함수 중 하나를 사용하여 겹치는 작업이 완료된 시기를 결정합니다. HasOverlappedIoCompleted 매크로를 사용하여 완료를 폴링할 수도 있습니다.

보류 중인 모든 비동기 I/O 작업을 취소하려면 CancelIoEx 함수를 사용하고 취소 요청을 지정하는 OVERLAPPED 구조를 제공합니다. CancelIo 함수를 사용하여 지정된 파일 핸들에 대한 호출 스레드에서 발급한 보류 중인 비동기 I/O 작업을 취소합니다.

겹치는 작업에는 FILE_FLAG_OVERLAPPED 플래그로 만든 파일, 명명된 파이프 또는 통신 디바이스가 필요합니다. 스레드가 겹치는 작업을 수행하기 위해 함수(예: ReadFile 함수)를 호출하는 경우 호출 스레드는 OVERLAPPED 구조체에 대한 포인터를 지정해야 합니다. (이 포인터가 NULL이면 함수 반환 값이 작업이 완료되었음을 잘못 나타낼 수 있습니다.) 이벤트가 I/O 작업의 완료를 알리는 데 사용되지 않는 한 OVERLAPPED 구조체의 모든 멤버를 0으로 초기화해야 합니다. 이벤트를 사용하는 경우 OVERLAPPED 구조체의 hEvent 멤버는 할당된 이벤트 개체에 대한 핸들을 지정합니다. 시스템은 작업이 완료되기 전에 I/O 함수에 대한 호출이 반환될 때 이벤트 개체의 상태를 서명되지 않은 상태로 설정합니다. 시스템은 작업이 완료될 때 이벤트 개체의 상태를 신호로 설정합니다. 이벤트는 동시에 둘 이상의 미해결 I/O 작업이 있는 경우에만 필요합니다. 이벤트가 사용되지 않는 경우 완료된 각 I/O 작업은 파일, 명명된 파이프 또는 통신 디바이스에 신호를 보냅니다.

겹치는 작업을 수행하기 위해 함수를 호출하면 함수가 반환되기 전에 작업이 완료될 수 있습니다. 이 경우 작업이 동기적으로 수행된 것처럼 결과가 처리됩니다. 그러나 작업이 완료되지 않은 경우 함수의 반환 값은 FALSE이고 GetLastError 함수는 ERROR_IO_PENDING 반환합니다.

스레드는 다음 두 가지 방법 중 하나를 통해 겹치는 작업을 관리할 수 있습니다.

  • GetOverlappedResult 또는 GetOverlappedResultEx 함수를 사용하여 겹치는 작업이 완료될 때까지 기다립니다. GetOverlappedResultEx를 사용하는 경우 호출 스레드는 겹치는 작업에 대한 시간 제한을 지정하거나 경고 대기를 수행할 수 있습니다.
  • WAIT 함수 중 하나에서 OVERLAPPED 구조체의 수동 재설정 이벤트 개체에 대한 핸들을 지정한 다음 대기 함수가 반환된 후 GetOverlappedResult 또는 GetOverlappedResultEx를 호출합니다. 함수는 완료된 겹치는 작업의 결과를 반환하고 이러한 정보가 적절한 함수의 경우 전송된 실제 바이트 수를 보고합니다.

단일 스레드에서 여러 동시 겹치는 작업을 수행하는 경우 호출 스레드는 각 작업에 대해 OVERLAPPED 구조를 지정해야 합니다. 각 OVERLAPPED 구조는 다른 수동 재설정 이벤트 개체에 대한 핸들을 지정해야 합니다. 겹치는 작업 중 하나가 완료될 때까지 기다리려면 스레드는 다중 개체 대기 함수 중 하나에서 모든 수동 재설정 이벤트 핸들을 대기 조건으로 지정합니다. 다중 개체 대기 함수의 반환 값은 신호를 받은 수동 재설정 이벤트 개체를 나타내므로 스레드는 대기 작업이 완료된 겹치는 작업을 확인할 수 있습니다.

이벤트 개체를 지정하거나 여러 작업에 동일한 이벤트 개체를 다시 사용하는 대신 겹치는 각 작업에 별도의 이벤트 개체를 사용하는 것이 안전합니다. OVERLAPPED 구조에 이벤트 개체가 지정되지 않은 경우 시스템은 겹치는 작업이 완료되면 파일, 명명된 파이프 또는 통신 디바이스의 상태를 신호합니다. 따라서 이러한 핸들을 대기 함수에서 동기화 개체로 지정할 수 있지만, 동일한 파일, 명명된 파이프 또는 통신 디바이스에서 동시에 겹치는 작업을 수행할 때 개체의 상태가 신호를 받은 작업을 알 수 없기 때문에 이 용도로 사용하기는 어려울 수 있습니다.

스레드는 해당 스레드의 겹치는 작업으로만 이벤트를 신호로 보낼 것이라는 가정 하에 이벤트를 재사용해서는 안 됩니다. 완료 중인 겹치는 작업과 동일한 스레드에서 이벤트가 신호를 보냅니다. 여러 스레드에서 동일한 이벤트를 사용하면 해당 이벤트를 사용하는 다른 스레드에 대해 작업이 처음 및 조기에 완료되는 스레드에 대해 이벤트가 올바르게 신호를 받는 경합 상태가 될 수 있습니다. 그런 다음 겹치는 다음 작업이 완료되면 겹치는 모든 작업이 완료될 때까지 해당 이벤트를 사용하는 모든 스레드에 대해 이벤트가 다시 신호를 보냅니다.

겹치는 작업, 완료 루틴 및 GetOverlappedResult 함수의 사용을 보여 주는 예제는 파이프 사용을 참조하세요.

Windows Vista, Windows Server 2003 및 Windows XP:

OVERLAPPED 구조를 다시 사용할 때는 주의해야 합니다. OVERLAPPED 구조체가 여러 스레드에서 재사용되고 bWait 매개 변수가 TRUE로 설정된 상태에서 GetOverlappedResult가 호출되는 경우 호출 스레드는 구조를 다시 사용하기 전에 연결된 이벤트에 신호를 보내야 합니다. GetOverlappedResult를 호출한 후 WaitForSingleObject 함수를 사용하여 작업이 완료될 때까지 스레드가 대기하도록 강제하여 이 작업을 수행할 수 있습니다. 이벤트 개체는 수동 재설정 이벤트 개체여야 합니다. 자동 집합 이벤트 개체를 사용하는 경우 bWait 매개 변수가 TRUE로 설정된 GetOverlappedResult를 호출하면 함수가 무기한 차단됩니다. 이 동작은 Windows 7을 애플리케이션 매니페스트에서 지원되는 운영 체제로 지정하는 애플리케이션의 경우 Windows 7 및 Windows Server 2008 R2부터 변경되었습니다. 자세한 내용은 애플리케이션 매니페스트를 참조하세요.

I/O 개념