4. 1.1 Overlapped IO
IOCP 를 알기 위해선 Overlapped 소켓 IO 모델을 먼저 이해해야 한다.
- Overlapped : IO 작업이 다른 IO, 혹은 다른 작업과 중첩되어 처리된다는 이야기.
- IO를 요청하고 기다릴 필요 없이 리턴 (논 블로킹 소켓)
- 나중에 이 작업 완료 여부를 체크할 수 있는데(비동기), 이 방법 중 하나가 IOCP이다.
- 소켓을 이용한 Network IO뿐 아니라 File IO 등에도 적용.
5. 1.1 Overlapped IO
장점
제일 먼저, IO Blocking이 일어나지 않는다.
- IO를 기다리지 않고 다른 작업을 처리할 수 있다.
버퍼링 오버헤드가 줄어든다.
- 일반 IO는 Disk에서 OS의 버퍼로, OS 버퍼에서 사용자 버퍼로 복사.
- Overlapped IO는 내가 지정한 버퍼에 바로 복사하게 된다.
6. 1.1 Overlapped IO
Select 모델과의 차이점
Select 모델
- IO 방식은 기존과 똑같이 하되, OS가 안전한 호출 시점을 알려준다.
(Select(...)가 반환되는 시점까지 대기)
Overlapped IO 모델
- IO 함수를 호출한 후, 완료 여부와 상관없이 다른 작업을 할 수 있다. (비동기 입출력)
- IO가 끝나면 OS가 이를 알려주고, 우리는 작업을 멈추고 IO 결과를 처리하면 된다.
(비동기 통지)
7. 1.1 Overlapped IO
윈도우 네트워크 프로그래밍에서 소개하는 Overlapped IO 모델 두 가지.
Overlapped IO 모델 (1)
- IO 작업이 끝나면 OS가 이벤트 객체를 Signaled 상태로 바꿔준다.
Overlapped IO 모델 (2)
- IO 작업이 끝나면 OS가 콜백 함수를 호출해준다.
- Overlapped IO 모델에서는 완료 루틴(Completion Routine)이라고 부른다.
- 이 PPT에서는 2번째 모델 위주로 소개.
8. 1.2 구동 원리
Overlapped IO가 가능한 소켓을 만들어 준다.
Socket을 사용하지 않고 WSASocket을 사용하는 이유.
- 기존 BSD타입 Socket도 Overlapped IO를 사용할 수는 있지만,
Windows에서만 동작 가능한 확장기능을 사용하고, Windows 플랫폼에서 더 효율적인
프로그래밍을 가능하게 하기 때문에.
출처 : https://kldp.org/node/102187
SOCKET WSASocket(int af, int type, int protocol, // 기존 소켓 생성 함수와 동일
LPWSAPROTOCOL_INFO lpProtocolInfo, // 생성되는 소켓의 특성정보 구조체
주소
GROUP group, // 함수의 확장을 위해 예약된 매개변
수, 보통 0.
DWORD dwFlags // 소켓의 속성정보 전달,
// Overlapped I/O라면 WSA_FLAG_OVERLAPPED
); // 성공시 소켓 핸들, 실패시
INVALID_SOCKET 반환
9. 1.2 구동 원리
1. 비동기 입출력 함수를 호출하여 OS에 입출력 작업을 요청
- 총 13개의 비동기 지원 소켓 함수가 있다.
- 사용할 것은 WSASend와 WSARecv (UDP의 경우 WSASendTo, WSARecvFrom)
10. 1.2 구동 원리
int WSASend( SOCKET s, // 소켓
LPWSABUF lpBuffer, // WSA버퍼 구조체 주소
DWORD dwBufferCount, // 배열 길이정보
LPDWORD lpNumberOfBytesSent, // 전송된 바이트 수를 받을 주소
DWORD dwFlags, // 함수의 데이터 전송 특성 설정 값, 우선 0을 넣는다.
LPWSAOVERLAPPED lpOverlapped, // Overlapped 구조체 주소 (Overlapped Model 1)
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // 완료 루틴 주소
); // 반환 값 : 성공시 0, 실패시 SOCKET_ERROR 반환
11. 1.3 사용 함수
typedef struct __WSABUF
{
u_long len; // 전송할 데이터 크기
char * buf; // 버퍼 주소
} WSABUF, *LPWSABUF;
typedef struct _WSAOVERLAPPED
{
DWORD Internal; // 운영체제가 내부적으로 사용하는 변수들
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
WSAEVENT hEvent; // Overlapped Model 1에서 사용하는 이벤트 객체.
} WSAOVERLAPPED, *LPWSAOVERLAPPED;
12. 1.2 구동 원리
2. 호출한 스레드는 Alertable Wait 상태에 진입
- 비동기 입출력을 위한 특별한 대기 상태로,
대기 시간이 끝나기 전에 완료 루틴이 호출되어 CPU 시간을 사용한 뒤 상태가 끝나는 상태이다
13. 1.2 구동 원리
3. 비동기 IO가 끝나면 OS는 APC 큐에 결과를 저장한다.
- APC 큐 (Asynchronous Procedure Call Queue) :
OS가 비동기 입출력 결과 저장을 위해 각 스레드마다 할당하는 메모리
14. 1.2 구동 원리
4. APC 큐에 저장된 정보를 참조하여 완료 루틴을 호출한다.
- 완료 루틴 내부에서는 데이터를 처리한 후 다시 비동기 IO를 호출할 수 있다.
- 모든 비동기 IO가 끝나면 스레드는 alertable wait 상태에 빠져나온다.
18. 2.1 IOCP
입출력 완료 포트(IOCP)라 부르는 Windows가 제공하는 커널 오브젝트를 활용하는 것.
- 비동기 IO 결과와, 이를 처리할 스레드에 대한 정보를 담고 있다.
- Overlapped IO의 APC 큐와 비슷한 개념.
Why IOCP?
- Select & Overlapped IO 모델은 : 싱글 쓰레드 멀티 플렉싱.
- 근데 요즘은 핸드폰도 다 멀티 코어인걸...
- 딱 정해진 쓰레드 개수만 사용하는 서버를 만들고 싶다!
19. 2.1 IOCP
vs APC 큐
- APC 큐는 각 스레드마다 자동으로 생성되고 파괴된다.
- IOCP는 CreateIoCompletionPort 함수로 생성하고, CloseHandle로 파괴한다.
- APC 큐의 결과는 APC 큐를 소유한 스레드만 확인할 수 있지만, IOCP에는 이러한
제약이 없다. 따라서 IOCP를 접근하는 여러 스레드를 두고 결과를 처리한다.
20. 2.2 구동 원리
1. IO Completion Port를 만든다.
- CreateIoCompletionPort 함수 호출.
- IOCP를 만드는 역할과 SOCKET을 만든 IOCP에 등록하는 두 가지 역할을 한다.
(따라서 랩핑 함수를 사용하여 쓰는 것이 좋을 것 같다.)
25. 2.2 구동 원리
BOOL WINAPI GetQueuedCompletionStatus(
_In_ HANDLE CompletionPort, // Dequeue할 IOCP 핸들
_Out_ LPDWORD lpNumberOfBytes, // IO 연산의 결과로 전송된 데이터 크기.
_Out_ PULONG_PTR lpCompletionKey, // CompletionKey를 저장할 포인터.
_Out_ LPOVERLAPPED *lpOverlapped, // 비동기 IO 호출시 지정한 Overlapped 구조체 포인터.
_In_ DWORD dwMilliseconds // 대기시간이 지날 때까지 완료가 되지 않으면 FALSE 리턴.
);
Worker Thread가 Waiting Thread Queue에서 이 함수를 물고 대기하게 된다.
26. 2.2 구동 원리
BOOL WINAPI PostQueuedCompletionStatus(
_In_ HANDLE CompletionPort,
_In_ DWORD dwNumberOfBytesTransferred,
_In_ ULONG_PTR dwCompletionKey,
_In_opt_ LPOVERLAPPED lpOverlapped
);
이 함수를 호출하여 IO 작업 완료가 아니더라도 정보를 직접 넣어줄 수도 있다.
다른 쓰레드에 어떤 완료 통지를 보내고자 할 때 유용.
27. 6. 새로운 소켓을 생성하면 3~5를, 그렇지 않으면 4~5를 반복한다.
2.2 구동 원리
28. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
CPU 코어가 2개인 컴퓨터에서 Socket을 연결한 IOCP를 사용하는 상황
Thread 1 Thread 2 Thread 3 Thread 4
29. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
이 상황에서 2개의 IO작업이 완료되었다.
Thread 1 Thread 2 Thread 3 Thread 4
IO Completion 1 IO Completion 2
30. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
IO Completion을 처리하기 위해 Waiting Thread Queue에
가장 최근에 들어온 스레드 2개를 깨운다 (LIFO)
Thread 1 Thread 2 Thread 3 Thread 4
Thread 4 Thread 3
31. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
Release Thread List에 이미 2개의 쓰레드가 돌고 있기 때문에
새로운 IO Completion이 들어와도 새로운 쓰레드는 깨우지 않는다.
Thread 1 Thread 2
Thread 4 Thread 3
IO Completion 3 IO Completion 4
32. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
이때 Thread 4에서 어떤 함수가 호출되어 Thread가 대기 상태에 빠지게 된다면?
Thread 1 Thread 2
Thread 4 Thread 3
IO Completion 3 IO Completion 4
Thread 4
33. 2.3 구동 예시
출처 : 남현욱님 IOCP 기본 구조 이해 https://www.slideshare.net/namhyeonuk90/iocp
장치 리스트
SOCKET
IO Completion Queue
Waiting Thread Queue
Release Thread List
Pause Thread List
IOCP는 항상 스레드 개수를 가능한 많이 사용하려하기 때문에
Waiting하고 있던 Thread를 하나 새로 깨워서 작업한다.
만약 이 상태에서 Pause Thread List의 쓰레드의 대기 작업이 끝나더라도
Release Thread List에 자리가 남을 때까지는 들어오지 못한다.
Thread 1 Thread 2
Thread 3
IO Completion 3 IO Completion 4
Thread 4
Thread 2
35. 감사합니다
NEXT 141060 이근원
출처 :
윈도우즈 네트워크 프로그래밍 (김선우 저)
남현욱님 IOCP 기본 구조 이해 (https://www.slideshare.net/namhyeonuk90/iocp)
김연우님 IOCP 개념 및 Overlapped IO (http://ozt88.tistory.com/23)
(http://ozt88.tistory.com/22)
KLDP - WSASocket을 사용하는 이유 (https://kldp.org/node/102187)
Overlapped IO와 IOCP 이야기 (이기탁님 글)