사용자 도구

사이트 도구


kb:iocp

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:iocp [2014/11/07 20:08] (현재)
줄 1: 줄 1:
 +====== IOCP ======
 +{{iocp.gif}}
 +
 +I/O Completion Port는 사용하기에 그렇게 복잡한 구조는 아니다.
 +
 +커널 스레드와 사용자(프로그래머)의 워커 스레드가 존재한다. 사용자가 어딘가에서 WSASend, WSARecv, PostQueuedCompletionStatus 함수 중에 하나를 이용해 IO 요청을 CP 쪽으로 넘긴다. 그러면 CP는 커널 스레드에게 방금 받은 IO를 실제로 처리할 것을 명령한다. 성공하든 실패하든 언젠가 IO가 완료될 것이다. 이 결과값은 커널 내부에 있는 큐에 들어있다가,​ 사용자가 GetQueuedCompletionStatus 함수를 호출하면 큐에서 나오는 것이다.
 +
 +
 +====== 주의할 점 ======
 +===== - GetQueuedCompletionStatus =====
 +from http://​xania.org/​200807/​iocp
 +
 +^ Return value ^ OVERLAPPED ^ number of bytes ^ Description ^
 +| zero | NULL | n/a | The call to GetQueuedCompletionStatus failed, and no data was dequeued from the IO port. This usually indicates an error in the parameters to GetQueuedCompletionStatus. |
 +| zero | non-NULL | n/a | The call to GetQueuedCompletionStatus failed, but data was read or written. The thread must deal with the data (possibly freeing any associated buffers), but there is an error condition on the underlying HANDLE. Usually seen when the other end of a network connection has been forcibly closed but there’s still data in the send or receive queue. |
 +| non-zero | NULL | n/a | This condition doesn’t happen due to IO requests, but is useful to use in combination with PostQueuedCompletionStatus as a way of indicating to threads that they should terminate. |
 +| non-zero | non-NULL | zero | End of file for a file HANDLE, or the connection has been gracefully closed (for network connections). The OVERLAPPED buffer has still been used; and must be deallocated if necessary. |
 +| non-zero | non-NULL | non-zero | “num bytes” of data have been transferred into the block pointed by the OVERLAPPED structure. The direction of the transfer is dependant on the call made to the IO port, it’s up to the user to remember if it was a read or a write (usually by stashing extra data in the OVERLAPPED structure). The thread must deallocate the structure as necessary. |
 +
 +===== - Locked page limit, Non-paged pool limit =====
 +==== - Locked page limit ====
 +데이터를 보내거나 받을 때, setsockopt 함수를 이용해 SO_SNDBUF와 SO_RCVBUF를 0으로 설정한 경우, 함수(WSASend,​ WSARecv)에 넘기는 버퍼들이 포함된 페이지들은 램(RAM)에서 페이지 아웃되지않도록 락이 걸린다. 커널 드라이버들이 이 버퍼를 액세스해야하기 때문에 락이 걸릴 수 밖에 없다. ​
 +
 +문제는 OS 입장에서 보면, 한 애플리케이션이 이런 식으로 램을 모두 차지해 버리면, 다른 애플리케이션들을 실행할 수 없으므로 곤란하다는 점이다. 그래서 Windows에서는 한 애플리케이션이 차지할 수 있는 락이 걸린 페이지의 양을 제한하고 있다. 대략 실제 램의 8분의 1 정도라고 한다. 이 제한에 다다른 경우, 즉 진행 중인 send/recv 작업이 너무 많을 때, IOCP를 사용한 작업들은 ERROR_INSUFFICIENT_RESOURCES 에러값을 내뱉으며 실패하게 된다. ​
 +
 +락의 기준이 페이지 단위라는 것을 유념하기 바란다. 페이지 크기보다 작은 버퍼를 사용해도,​ 락이 걸리는 것은 페이지 단위이므로,​ 페이지 크기에 버퍼 크기를 맞추는 것이 페이지를 최대로 활용하는 방법이다.
 +
 +==== - Non-paged pool limit ====
 +Windows NT/2000 드라이버들은 non-paged pool이라는 특별한 장소에서 메모리를 할당할 수 있다. 이 풀에다 할당한 메모리는 페이지 아웃되지 않는다. 이 풀은 다양한 커널 모드 컴포넌트들에게 필요한 정보를 저장해 두기 위한 것이다. 컴포넌트 중에 페이지 아웃된 메모리는 액세스할 수 없는 것들도 있기 때문이다. ​
 +
 +애플리케이션에서 소켓을 생성할 때 이 풀의 공간을 약간 소모한다. bind/​connect/​WSASend/​WSARecv 호출 시에도 약간씩 소모한다. 접속자 수가 많아지면,​ 언젠가는 문제가 생긴다는 걸 알 수 있을 것이다. 풀에 더 이상의 공간이 없을 경우, 제대로 작성되지 않은 드라이버 등에 의해서 시스템 크래시가 일어날 수도 있다.
 +
 +==== - 해결 방안 ====
 +리소스 제한을 관리하는 것은 쉽지 않다. 리소스가 모자랄 때, 특별한 에러 코드가 반환되거나,​ 예외가 뜨는 것이 아니라, 다양한 시스템 함수 호출에서,​ 일반적인 WSAENOBUFS 또는 ERROR_INSUFFICIENT_RESOURCES 에러가 반환될 뿐이기 때문이다. ​
 +
 +어쨌든 이를 해결하기 위해서는 첫번째로 워킹셋(Working Set)의 크기를 늘려야한다. 두번째는 네트워크 대역폭을 초과하지 않았는지 체크해야 한다. 그 다음에는 너무 많은 send/recv 요청을 동시에 진행중이지는 않은지 체크해야 한다. 그래도 안 된다면, 정상적인 연결을 끊어서, 메모리를 확보하는 수 밖에 없다.
 +
 +
 +====== 목록 ======
 +  * [[Scrap:​ScalableWinsockAppsUsingCompletionPorts]]
 +
 +
 +====== 링크 ======
 +  * [[http://​www.sysinternals.com/​ntw2k/​info/​comport.shtml Inside I/O Completion Ports]]
 +  * [[http://​www.codeproject.com/​internet/​jbsocketserver1.asp A reusable, high performance,​ socket server class - Part 1]]
 +  * [[http://​www.codeproject.com/​internet/​jbsocketserver2.asp A reusable, high performance,​ socket server class - Part 2]]
 +  * [[http://​www.codeproject.com/​internet/​jbsocketserver3.asp A reusable, high performance,​ socket server class - Part 3]]
 +  * [[http://​www.codeproject.com/​internet/​reusablesocketserver4.asp Handling multiple pending socket read and write operations]]
 +
 +  * [[http://​support.microsoft.com/​default.aspx?​scid=kb;​EN-US;​q192800 MSKB > Design Issues When Using IOCP in a Winsock Server]]
 +  * [[http://​support.microsoft.com/​default.aspx?​scid=kb;​en-us;​181611 MSKB > Socket Overlapped I/O Versus Blocking/​Non-blocking Mode]]
 +
 +----
 +  * see also [[NetworkIoStrategy]],​ [[AlertableIo]]
  
kb/iocp.txt · 마지막으로 수정됨: 2014/11/07 20:08 (바깥 편집)