[Chapter 19] 비동기(Asynchronous) I/O 와 APC

·2022년 11월 6일

※ 아래는 윤성우 뇌를 자극하는 윈도우즈 프로그래밍 한빛미디어(주) 2022년
Chapter19(p.635 ~ 668)를 읽고 정리한 내용입니다.

01 비동기 I/O의 이해

한번 호출되면 완료될 때까지 블로킹되는 함수들을 블로킹 함수라 하고,
이 함수들을 활용한 입,출력 연산을 동기 I/O라 표현한다.

I/O 작업을 계속 하면서 버퍼링된 데이터를 기반으로 플레이를 계속 하는 구조의 I/O를 비동기 I/O라 한다.

02 중첩(Overlapped) I/O

Windows에서 제공하는 비동기 I/O 방식 중에서 가장 대표적인 방식으로
넌블로킹 함수를 통해 여러 작업이 동시에 진행될 수 있게 한다.
(넌블로킹 함수는 작업의 완료에 상관없이 바로 반환해 버리는 특성을 지님 -> 반환 후에도 작업은 계속됨)
ANSI 표준 함수에는 넌블로킹이라는 개념이 존재하지 않음
-> Windows 시스템 함수를 통해 넌블로킹 방식으로 동작시킬 수 있음
(예) fread 함수 대신 ReadFile 함수 사용

03 완료루틴(Completion Routine) 기반 확장 I/O

중첩 I/O는 입력 및 출력이 완료되었음을 확인하는 번거로운 작업을 항시 고려해야 한다.
-> I/O 연산이 완료되었을 때 실행되는 루틴을 완료루틴이라 한다.

  • 확장 I/O 제공 기능 = 중첩 I/O 제공 기능 + α(알파)
BOOL WriteFileEx(HANDLE hFile, // 데이터 전송(쓰기)의 대상 핸들 지정
							   // 해당 핸들은 FILE_FLAG_OVERLAPPED 속성이 지정되어야 함
				 LPCVOID lpBuffer, // 전송할 데이터를 지니는 버퍼의 주소
                 DWORD nNumberOfBytesToWrite, // 전송할 데이터의 크기를 지정
                 LPOVERLAPPED lpOverlapped, // 구조체 변수의 포인터 지정
                 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
                 // 출력 연산 완료 시 자동으로 호출되는 완료루틴의 지정을 위해 사용됨
                 
BOOL ReadFileEx(HANDLE hFile, // 데이터 수신 대상 지정
							  // 해당 핸들은 FILE_FLAG_OVERLAPPED 속성을 지녀야 함
				LPVOID lpBuffer, // 데이터 수신을 위한 버퍼의 주소 지정
                DWORD nNumberOfBytesToRead, // 읽어 들일 데이터의 최대 크기를 바이트 단위로 지정
                							// 보통 버퍼의 최대 길이를 바이트 단위로 지정
                LPOVERLAPPED lpOverlapped, // OVERLAPPED 구조체 변수의 포인터 지정
                LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); 
                // 입력 연산 완료시 자동으로 호출되는 완료루틴 지정

04 APC(Asynchronous Procedure Call)

APC는 크게 두 가지 종류로 나뉜다
(1) User-mode APC
(2) Kernel-mode APC

(참고)Kernel-mode APC는 Normal Kernel-mode APC와 Special Kernel-mode APC로 나뉜다.

모든 쓰레드는 자신만의 APC Queue를 가진다.
APC Queue는 비동기적으로 호출되어야 할 함수들과 매개변수 정보가 저장된다.
저장됐다고 함수가 바로 호출되는 것은 아니고 쓰레드가 알림 가능 상태에 놓이게 될 때 호출된다.

APC Queue의 접근

APC Queue에 함수 정보를 전달하는 방법은 지금까지 정리한 내용 기준으로 총 세 가지이다.
(1) WriteFileEx
(2) ReadFileEx
(3) SetWaitableTimer

그러나 다음 함수를 이용하면 직접적으로 APC Queue에 호출하고자 하는 함수 정보를 전달할 수 있다.

DWORD QueueUserAPC(PAPCFUNC pfnAPC, // 비동기로 호출될 함수를 지정한다.
									// 이 함수를 통해서 지정할 수 있는 함수의 타입은 다음과 같은 형태로 제한된다.
                                    // VOID CALLBACK APCProc(ULING_PTR dwParam);
				   HANDLE hThread, // 비동기 함수 정보를 추가할 APC Queue를 지정한다.
                   				   // APC Queue를 소유하는 쓰레드 핸들을 지정한다.
                   ULONG_PTR dwData); // APC Queue에 등록된 함수 호출 시 전달할 인자를 지정한다.

0개의 댓글