Search Results for 'Server/IOCP'

4 POSTS

  1. 2012.08.13 GetQueuedCompletionStatus() 함수
  2. 2012.08.13 Completion Port 오브젝트와 소켓의 연결
  3. 2012.08.13 Completion Port의 생성
  4. 2012.08.13 IOCP

GetQueuedCompletionStatus() 함수

Posted 2012. 8. 13. 22:49

이제 CP에 등록되는 완료된 IO의 확인방법. 이에 사용되느 함수는

 

BOOL GetQueuedCompletionStatus(

HANDLE CompletionPort,  //완료된 IO정보가 등록되어있는 CP오브젝트의 핸들 전달      

LPDWORD lpNumberOfBytes,  // 입출력 과정에서 송수신 된 데이터의 크기정보를 저장할 변수의 주소값

PULONG_PTR lpCompletionKey,   // CreateIoCompletioPort함수의 세번쨰 인자로 전달된 값의 저장을위한 변수의 주소값

LPOVERLAPPED* lpOverlapped,  // WSASend, WSARecv 함수호출시 전달하는 OVERLAPPED구조체변수의주소값이저장될변수의 주소값 전달

DWORD dwMillisecones   // 타임아웃 정보전달, ㅕㅇ기서 지정한 시간이 완료되면 FALSE를 반환하면서 함수를 빠져나감.

INFINITE-> 완료된 IO가 CP오브젝트에 등록될때까지 블로킹상태.

);

-> 성공시 TRUE, 실패시 FALSE 반환

 

" GetQueuedCompletionStatus 함수의 세번째 인자를 통해서 얻게 되는 것은 소켓과 CP오브젝트의 연결을 목적으로

CreateCompletionPort 함수가 호출될때 전달되는 네번째 인자 값이다.

네번째 인자로 얻게되는건  WSASend, WSARecv함수호출시 전달되느 WSAOVERLAPPED구조체 변수의 주소값이다.

 

'Server > IOCP' 카테고리의 다른 글

Completion Port 오브젝트와 소켓의 연결  (0) 2012.08.13
Completion Port의 생성  (0) 2012.08.13
IOCP  (0) 2012.08.13

생성했다면 오브젝트에 연결해야됨..그래야 완료된 소켓의 IO정보가 CP오브젝트에 등록된다.

 

생성과 연결 함수

HANDLE CreateIoCompletionPort(

HANDLE FileHandle,

HANDLE ExistingCompletionPort,

ULONG_PTR CompletionKey,

DWORD NumberOfConcurrentThreads

);

이번은 연결시점으로 설명)

HANDLE FileHandle     // CP오브젝트에 연결할 소켓의 핸들 전달

 

HANDLE ExistingCompletionPort,    // 소켓과 연결할 CP오브젝트의 핸들 전달

ULONG_PTR CompletionKey,      //완료된 IO관련 정보의 전달을 위한 매개변수. 이는 GetQueuedCompletionStatus함수와 함꼐이해해야됨

DWORD NumberOfConcurrentThreads    // 어떠한 값을 전달하건 이 함수의 두번째 매개변수가 NULL이아니면 그냥 무시됨.

 

ex)

HANDLE hCpObject;

SOCKET hSock;

........

CreateIoCompletionPort( (HANDLE)hSock, hCpObject, (DWORD)ioInfo, 0 );

이렇게 Crea......함수가 호출된 이후부터는 hSock를 대상으로 진행된 IO가 완료되면 이에대한 정보가 핸들 hCpObject에 해당하는 CP오브젝트에 등록된다.

 

'Server > IOCP' 카테고리의 다른 글

GetQueuedCompletionStatus() 함수  (0) 2012.08.13
Completion Port의 생성  (0) 2012.08.13
IOCP  (0) 2012.08.13

Completion Port의 생성

Posted 2012. 8. 13. 22:48

IOCP에선 완료된 IO의 정보가 Completion Port 오브젝트(이하 CP 오브젝트)라는 커널 오브젝트에 등록된다.

" 이 소켓을 기반으로 진행되는 IO의 완료상황은 저 CP오브젝트에 등록해 주세요 " 라는 요청의과정이 선행되어야 한다.

이를 가리켜 소켓과 CP오브젝트와의 연결 요청 이라 한다.

때문에 IOCP 모델의 서버 구현을 위해서는 다음 두 가지 일을진행해야 한다

1.Completion Port 오브젝트의 생성

2.Completion Port 오브젝트와 소켓의 연결

이떄 소켓은 반드시 Overlapped 속성이 부여된 소켓이여야 함.

 

생성과 연결 함수

HANDLE CreateIoCompletionPort(

HANDLE FileHandle,

HANDLE ExistingCompletionPort,

ULONG_PTR CompletionKey,

DWORD NumberOfConcurrentThreads

);

-> 성공시 CP 오브젝트의 핸들, 실패시 NULL 반환

지금은 생성이니까 생성시점으로 설명)

  1. 입출력 완료 포트를 새로 생성하고
  2. 소켓과 입출력 완료 포트를 연결한다. 연결하면 이 소켓에 비동기 입출력 결과가 입출력 완료 포트에 저장된다.

 

FileHandle : 새로운 입출력 완료포트를 생성할때는 INVALID_HANDLE_VALUE를 전달

ExistingCompletionPort : 파일 또는 소켓과 연결할 입출력 완료 포트 핸들. 새로운입출력 완료 포트를 생성할땐 NULL 전달

CompletionKey : 입출력 완료 패킷에 들어갈 부가적인 정보를 32비트 값을 줄수있다. 생성시는 0을 전달

NumberOfConcurrentThreads : 동시에 실행할수있는 작업자 스레드의 개수. 0을 사용하면 자동으로 CPU개수와 같은수로 설정.

                                         최대설정수는 2.

 

ex) HANDLE hCpObject;

......

hCpObject = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 2 );

 

SOCKET sock;

HANDLE hResult = CreateIoCompletionPort( ( HANDL)sock, (DWORD)sock, 0 );

 

 

결론은 생성할땐 생성옵션에 맞춰서 함수를 호출하고 연결할땐 연결옵션에 맞춰서 함수를 호출.

 

즉.. 만들때 한번호출하고.. 이미 있는걸 연결할때 또 호출하고..

 

 

 

 

 

 

 

'Server > IOCP' 카테고리의 다른 글

GetQueuedCompletionStatus() 함수  (0) 2012.08.13
Completion Port 오브젝트와 소켓의 연결  (0) 2012.08.13
IOCP  (0) 2012.08.13

IOCP

Posted 2012. 8. 13. 22:48

Completion Port모델은 모든 소켓 입출력 모델 중 가장 뛰어난 성능을 제공한다.

보통 입출력 완료포트( I/O Completion Port ) 를 줄여서 IOCP라 칭한다.

 

입출력 완료포트는 비동기 입출력 결과와 이 결과를 처리할 스레드에 대한 정보를 담고 있는 구조로 APC큐와 비슷한 개념이다.

APC : 비동기 함수를 호출하는 매커니즘

 

APC와 IOCP의 차이점

1, 생성과 파괴

-> APC큐는 각 스레드마다 자동으로 생성되고 파괴된다.

-> IOCP는 CreateIoCompletionPort() 함수를 호출하여 생성하고 CloseHandle() 함수를 호출하여 파괴한다.

 

2. 접근 제약

->APC큐는 저장된 결과는 APC큐를 소유한 스레드만 확인할수 있지만 IOCP에는 이런 제약이 없다.

-> 보통 입출력 완료 포트를 접근하는 스레드를 별도로 두는데 이를 작업스레드라 한다.

 

3.  비동기 입출력 처리 방법  

->APC큐는 저장된 결과를 처리하려면 해당 스레드는 alertable wait 상태에 진입해야 한다.

-> IOCP에 저장된 결과를 처리하려면 작업자 스레그는 GetQueuedCompletionStatus() 함수를 호출해야 한다.

 

IOCP 소켓 입출력 절자

  1. CreateIocompletionPort() 함수를 호출하여 입출력 완료 포트를 생성
  2. CPU 개수에 비례하여 작업자 스레드를 생성

    모든 작업자 스레드는 GetQueuedCompletionStatus() 함수를 호출하여 대기 상태가 된다.

  3. 비동기 입출력을 지원하는 소켓을 생성한다.

    이 소켓에 대한 비동기 입출력 결과가 입출력 완료 포트에 저장되려면

    CreateIoCompletionPort() 함수를 호출하여 소켓과 입출력 완료 포트를 연결해야 한다.

  4. 비동기 입출력 함수를 호출한다.

    비동기 입출력 작업이 곧바로 완료되지 않으면 소켓 함수는 오류를 리턴하고 오류코드는 WSA_IO_PENDING으로 설정된다.

  5. 비동기 입출력 작업이 완료되면 운영체제는 입출력 완료 포트에 결과를 저장하고

    대기 중인 스레드 하나를 깨운다.

    대기 상태에서 깨어난 작업자 스레드는 비동기 입출력 결과를 처리한다.

  6. 새로운 소켓을 생성하면 3~5를.. 그렇지 않으면 4~5를 반복한다.

 

 

여기서 ...

IOCP에서는 IO를 전담하는 쓰레드를 별도로 생성하고 이 쓰레드가 모든 클라이언트를 대상으로 IO를 진행하게 됨.

입출력 함수인 WSASend, WSARecv 함수를 호출하는 쓰레드는 우리가 직접 생성해야 한다.

다만 이 쓰레드가 입출력의 완료를 위해 GetQueuedCompletionStatus함수를 호출할뿐이다.

그리고 GetQueue....함수는 어떤 스레드든 호출 가능하지만 실제 IO의 완료에 대한 응답을 받는 쓰레드의 수는 

CreateIoCompletionPort호출시 지정한 최대 쓰레드의 수를 넘지않는다.

 

적정수는 CPU에 존재하는 코어의 수로 이해하는것이 좋다.

 

워커쓰레드의 갯수가 cpu*2인 이유. MS의 표준임..

 

즉 IOCP란

Input Ouput Completion Port즉 인풋 아웃풋 작업이 완료 되었을때 포트를 통해서 일을 처리하는것을 말한다.

그 일이 워커쓰레드 에서 한다.

 

동기식 : send나 recv함수가 완료되기 전에는 실행 코드가 움직이지 않는다

비동기식 : send나 recv는 우선 운영체제에게 소켓 작업을 한다고 알려죽 ㅗ후에 완료 통지를 받는 방식이다.

중첩소켓 : 여러개의 소켓 입출력 작업이 운영체제로 들어가면 몇개는 입출력 시간이 겹쳐도 작업이 가능하다는 매우 획기적인 기술

               중첩되는 시간만큼 속도가 빨라진다는 장점을 가직 ㅗ있다.

 

비동기 I/O가 완료되면 정보단위가 만들어지고 이것이 IOCP큐에 들어간다. 이때 작업 스레드는 IOCP의 통지를 받고 IOCP큐에서 정보 단위 하나를 가져와

작업을 수행하게 된다.

IOCP는 하나의 스레드가 하나 이상의 사용자로부터의 요구를 처리 할 수 있도록 해준다. 꼭 한개의 스레드를 사용하는 건 아니다.

상황에 맞게 스레드의 개수를 조절 할 수 있다.

작업 스레드가 많으면 좋지만. 스레드가 많아지게 되면 context switching이 많이 일어 나므로 적은 수으 ㅣ스레드를 사용.

context switching은 윈도우 2000, nt 이상에서 지원해준다( 자동으로 해줌..)

IOCP의 가장 큰 장점은 쓰레드 풀을 통한 context switching 비용이 줄어든다. 

 

'Server > IOCP' 카테고리의 다른 글

GetQueuedCompletionStatus() 함수  (0) 2012.08.13
Completion Port 오브젝트와 소켓의 연결  (0) 2012.08.13
Completion Port의 생성  (0) 2012.08.13