4가지 방법이 있다.
방법 |
요약 |
디바이스 커널 오브젝트의 시그널링 |
단일의 장치에 대해 다수의 I/O 요청을 수행하는 경우 적합하지 않다. 특정스레드가 I/O요청을 하고 다른 스레드가 완료 통지를 수신할 수 있다. |
이벤트 커널 오브젝트의 시그널링 |
단일의 장치에 대해 다수의 I/O 요청을 수행할 수 있다. 특정스레드가 I/O요청을 하고 다른 스레드가 완료 통지를 수신할 수 있다. |
얼러터블 I/O 사용 |
단일의 장치에 대해 다수의 I/O 요청을 수행할 수 있다. 항상 I/O 요청을 한 스레드가 완료 통지를 수신한다. |
IOCP 사용 |
단일의 장치에 대해 다수의 I/O 요청을 수행할 수 있다. 특정 스레드가 I/O 요청을 하고 다른 스레드가 완료 통지를 수신할 수 있다. |
■ 디바이스 커널 오브젝트의 시그널링
말 그대로 디바이스 커널 오브젝트의 시그널링을 체크하는 방식이다.
예로, CreateFile() 의 결과값 (파일 디바이스의 커널 오브젝트) 을 가지고 WaitForSingleObject()를 이용하여
작업 완료시까지 대기하는 방식이다.
"단일 장치에 대해 다수의 I/O 요청을 수행하는 경우 적합하지 않다." 라는 의미는
동시에 두 개의 I/O 요청을 한 경우 완료되었을 때 어떤 요청의 완료인지에 대해 명확하게
파악을 할 수가 없기 때문에 적합하지 않다 라는 의미이다.
단적인 사용 예>
BOOL bReadDone = ::ReadFile(hFile, bBuffer, 100, NULL, &o);
DWORD dwError = ::GetLastError();
if ( !bReadDone && (dwError == ERROR_IO_PENDING))
{
WaitForSingleObject(hFile, INFINITE);
bReadDone = TRUE;
}
if (bReadDone) { // 성공 }
■ 이벤트 커널 오브젝트의 시그널링
이벤트 커널 오브젝트의 경우는 OVERLAPPED 의 hEvent 필드를 이용하기 때문에, 어떠한 I/O 요청인지
판단을 할 수가 있다. 이 때 반드시 각 요청별로 서도 다른 이벤트 커널 오브젝트를 생성해야 한다.
단적인 사용 예>
OVERLADDPED oRead = {0};
oRead.hEvent = CreateEvent();
::ReadFile(hFile, bBuffer, 100, NULL, &oRead);
OVERLADDPED oWrite = {0};
oRead.hEvent = CreateEvent();
::WriteFile(hFile, bBuffer, _countof(bBuffer), NULL, &oWrite);
HANDLE h[2];
h[0] = oRead.hEvent;
h[1] = oWrite.hEvent;
DWORD dw = WaitForMultipleObjects(2, h, FALSE, INFINITE);
// Read가 끝났는지, Write가 끝났는지 확인 가능하다.
■ 얼러터블 I / O
스레드가 생성되면 시스템은 각 스레드별로 비동기 프로시저 콜 (APC) 큐라는 것을 하나씩 생성한다.
비동기 I/O 요청을 전달하는 함수(ReadFileEx, WriteFileEx)를 호출하는 경우
디바이스 드라이버에게 I//O 작업 완료 통지를 스레드의 APC큐에 삽입해 줄 것을 요청할 수 있다.
VOID WINAPI CompletionRoutine (DWORD dwError, DWORD dwNumBytes, OVERLAPPED* po)
{
// dwError와 dwNumBytes는 po-> 를 이용해서도 구할 수 있다.
wprintf(L"po->Internal : %d, dwError : %d\n", po->Internal, dwError);
wprintf(L"po->InternalHigh : %d, dwNumBytes : %d\n", po->InternalHigh, dwNumBytes);
}
int wmain(void)
{
ReadFileEx (hFile, buffer, buffer count, &overladdped, CompletionRoutine);
// 스레드가 얼러터블 상태가 되면, 시스템은 APC큐의 내용을 확인하여 큐에 삽입된 모든 항목에 대해
// 컴플리션 루틴을 호출해 준다. 아래는 해당 스레드를 얼러터블 상태로 만드는 함수인 SleepEx을 이용한 예이다.
SleepEx(10, TRUE);
}
※ 스레드를 얼러터블 상태로 변경할 수 있는 함수
DWORD SleepEx ( DWORD dwMilliseconds, BOOL bAlertable);
DWORD WaitForSingleObjectEx (...);
DWORD WaitForMultipleObjectsEx(...);
BOOL SignalObjectAndWait(...);
BOOL GetQueuedCompletionStatusEx(...);
DWORD MsgWaitForMultipleObjectsEx(...);
'개발지식창고 > Serial통신' 카테고리의 다른 글
OVERLAPPED (0) | 2011.12.19 |
---|---|
Overlapped I/O (2) (0) | 2011.12.19 |
Overlapped I/O (1) (0) | 2011.12.19 |
Serial 통신 Cycle (0) | 2011.11.30 |