윈도우는 Overlapped I/O 모델을 사용하는데, 운영체제가 직접 입력 데이터를 유저 영역으로 복사하며, 복사가 완료된 시점에 통지를 해준다. 이 과정을 자세히 알아보자.
소켓은 기본적으로 블록/동기로 만들어진다. 여기서 데이터 입출력을 수행하는 동안 블록이 발생한다. 블록/논블록, 동기/비동기에 관한 설명은 링크를 참고.
이 모델로는 하나의 쓰레드에서 두 개 이상의 소켓을 다루기 힘들다. 하나의 소켓으로 데이터 입출력을 처리하는 동안 블록 되어 대기상태가 되기 때문이다. 이 모델을 사용하면서 두 개 이상의 소켓을 다루기 위해서는 멀티 쓰레드 기술을 사용해야 한다.
이 문제는 입출력 모델을 블록/비동기 또는 논블록/비동기를 사용하여 해결할 수 있다. 블록/비동기 모델을 사용하는 기술이 select
함수를 이용한 입출력 다중화이다. Overlapped I/O
모델은 논블록/비동기의 응용모델이다. Overlapped는 논블록 + (비동기적)완료 통보라고 보면 된다.
커널은 여러 개의 소켓의 데이터를 동시에 다룰 수 있다. 이를 통해 하나의 쓰레드 내에서 동시에 둘 이상의 영역으로 데이터 전송을 수행할 수 있다. 데이터의 입력이 완료되면, 해당 소켓에서 이벤트를 통지한다. 이벤트를 받은 프로세스는 이벤트 객체를 이용해서 데이터를 처리하거나 Completion Rutine(overlapped I/O 작업이 완료되면 시스템이 호출해주는 함수)를 이용해서 데이터를 처리할 수 있다. 중첩해서 들어올 수 있는 데이터의 처리를 커널에 맡 기게 되므로 유저 모드에서 블록 되는 일 없이 여러 개의 소켓을 처리할 수 있다.
다음은 논블록/비동기 모델을 따르는 프로그램의 흐름을 나타낸다.
- 읽기 함수를 호출하면, 커널은 데이터를 읽기 위한 초기화 작업을 하고 데이터를 기다린다. 읽기 함수는 바로 반환한다.
- 이제 프로그램은 다른 작업을 진행한다.
- 데이터가 입력되면, 이벤트가 발생한다.
- 프로그램은 콜백함수 혹은 이벤트 객체를 만들어서 데이터를 읽어서 처리한다.
리눅스의 입출력 다중화나 리얼 타임 시그널 등 비동기 입출력 기술과 차이점이 있다. 이들 리눅스 모델은 데이터 입력이 완료된 시점에서 데이터를 읽는 방식이 아니다. 소켓으로 데이터가 입력되는 시점에서 커널 데이터를 유저 데이터로 복사한다. 이 말은 커널로부터 데이터의 복사가 끝날 때까지 몇 번이나 입출력 함수를 호출할 수도 있음을 의미한다. 여러 번 유저 모드와 커널 모드 간의 변환이 있으므로 성능이 감소할 수밖에 없다.
윈도의 Overlapped I/O모델은 데이터 입출력이 완료된 시점에서 이벤트를 발생한다. 이로 인해 얻을 수 있는 이점은 다음과 같다.
- 모드 변환이 발생하지 않는다 : 여러 번의 데이터 복사가 발생하지 않는다
- 데이터 입출력이 진행되는 동안에도 다른 일을 할 수 있다.