I/O completion ports are used with asynchronous I/O. The
CreateIoCompletionPort function associates an I/O completion port with one or more file handles. When an asynchronous I/O operation started on a file handle associated with a completion port is completed, an I/O completion packet is queued to the port. This can be used to combine the synchronization point for multiple file handles into a single object.
{{|
IOCP는 비동기 I/O로 쓰인다. 이는
CreateIoCompletionPort 함수를 통해 하나 또는 다수의 파일핸들에 연결된다. Completion Port작업이
완료시에 비동기 I/O가 작동하며 이에 I/O Completion packet이 큐에 넣어진다. IOCP는 하나의 Object에 대한 다수의 파일 핸들을 동기화
시키는 데 사용한다.
|}}
A thread uses the
GetQueuedCompletionStatus function to wait for a completion packet to be queued to the completion port, rather than waiting directly for the asynchronous I/O to complete. Threads that block their execution on a completion port are released in last-in-first-out (LIFO) order. This means that when a completion packet is queued to the completion port, the system releases the last thread to block its execution on the port.
{{|
쓰레드는
GetQueuedCompletionStatus 함수를 통해 패킷이 포트에 들어오기 까지 Wait 된다. 이는 비동기 I/O를 위해 직접 쓰레드를 Wait하는
것 보다 낫다. 쓰레드의 실행이 블럭되고 이는 LIFO순서로 릴리즈 된다.(리쥼된다는말!)
|}}
When a thread calls
GetQueuedCompletionStatus, it is associated with the specified completion port until it exits, specifies a different completion port, or frees the completion port. A thread can be associated with at most one completion port.
{{|
쓰레드가
GetQueuedCompletionStatus를 호출 할때, 쓰레드가 종료되기 전까지 그 특정 포트는 쓰레드에 연결 되어 있다. 다른 Completion Port를 쓰던가 또는 그
Completion Port 를 Free하던가..... 쓰레드는 최대 하나의
CompletionPort에 연결 된다.
|}}
The most important property of a completion port is the concurrency value. The concurrency value of a completion port is specified when the completion port is created. This value limits the number of runnable threads associated with the completion port. When the total number of runnable threads associated with the completion port reaches the concurrency value, the system blocks the execution of any subsequent threads that specify the completion port until the number of runnable threads associated with the completion port drops below the concurrency value. The most efficient scenario occurs when there are completion packets waiting in the queue, but no waits can be satisfied because the port has reached its concurrency limit. In this case, when a running thread calls
GetQueuedCompletionStatus, it will immediately pick up the queued completion packet. No context switches will occur, because the running thread is continually picking up completion packets and the other threads are unable to run.
{{|
Completion Port의 가장 중요점은 동시에 쓰이는 값에 있다. Completion Port의 동시성은 포트가 생성될때 지정한다. 이 값은 Completion Port와 연결된 동작중인 쓰레드 수와
연관이 있으며, 총 동작중인 또 Completion Port와 연결된 쓰레드 수는 the concurrency value에 적용된다. ... 해석 NO ... 가장 효과적인 방법은 패킷이 queue에 들어오는
데로 쓰레드가 그 패킷을 가져오며 쓰레드가 동작중에
GetQueuedCompletionStatus를 호출해서 즉시 패킷을 가져오는 것이다. 문맥전환이 없고 계속적적으로 다른 쓰레드는 접근하
지 못하게 하고 하나의 쓰레드가 패킷을 얻어오는 것이다.
|}}
The best value to pick for the concurrency value is the number of
CPUs on the machine. If your transaction required a lengthy computation, a larger concurrency value will allow more threads to run. Each transaction will take longer to complete, but more transactions will be processed at the same time. It is easy to experiment with the concurrency value to achieve the best effect for your application.
{{|
가장 최적의 concurrency value는 CPU의 수에 관계된 것으로 (내가 알기로는 2*CPU수 + 2) 또는 "+1"의 쓰레드가 적당한 것으로 알고 있다.
|}}
The
PostQueuedCompletionStatus function allows an application to queue its own special-purpose I/O completion packets to the completion port without starting an asynchronous I/O operation. This is useful for notifying worker threads of external events.
{{|
PostQueuedCompletionStatus 함수는 어플리케이션이 비동기 I/O 명령어의 시작없이 자신의 특별한 목적의 I/O Completion 패킷을 가져오는 것을 허락한다.
이는 외부의 이벤트에 대해 쓰레드를 깨워(?:단순 notify)주는데 유용하다.
|}}
The completion port is freed when there are no more references to it. The completion port handle and every file handle associated with the completion port reference the completion port. All the handles must be closed to free the completion port. To close the port handle, call the
CloseHandle function.
{{|
Completion Port는 더 이상 참조가 없을 때 놓아지며 , 놓을 때에는 꼭
CloseHandle 함수를 불러라.
|}}
From MSDN
{{|
IOCP를 쓰는 이유
소켓의 경우 패킷이 들어오면 Opertiong System의 Buffer에 우선 쓰여지고 버퍼의 데이타가 일정치 쌓이면 이를 어플리케이션 버퍼에 Copy 한
다음 어플리케이션에 Receieve 메세지를 날려준다. 이는 쓸 데없이 버퍼의 값을 두번 쓰게 만드는 작업을 낳는다. 보다 속도를 향상 시키기 위해
어플리케이션과 Operationg System이 같은 버퍼의 메모리 위치를 참조하게 만드는 것이 IOCP이다.
파일 전송이나 지속적 연결 상태에서 연속적인 데이타를 보내주는 데 쓰이며 I/O 핸들에 Socket 핸들을 넣어준다는 것 외에 그렇게 어렵지 않다.
익혀두면 후에 보다 쉽게 네트워크 프로그램을 할 수 있을 것이다.
|}}
From fnwinter and Devipa