[39일차] | 컴퓨터 밑바닥의 비밀 | 책너두
6.4 높은 동시성의 비결: 입출력 다중화
- 유닉스/리눅스에서 파일은 단순히 N바이트의 수열이다.
- 또한, 모든 입출력 장치는 파일로 표현된다.
6.4.1 파일 서술자
- 파일을 식별하기 위해 파일 디스크립터(file descriptor)를 사용한다.
- 파일 디스크립터는 파일을 식별하는 정수값이다.
- 파일 디스크립터는 파일을 식별하는 유일한 값이다.
- 이를 통해, 프로세스는 파일에 대해 알지 않고도 입출력 작업을 수행할 수 있다.
6.4.2 다중 입출력을 어떻게 효율적으로 처리하는 것일까?
- 서버는 목적상 본질적으로 다수의 사용자와 통신해야 한다.
- 이러한 통신은 소켓으로 관리되며, 소켓 역시도 리눅스에서는 파일로 표현된다.
- 따라서, 수많은 파일 디스크립터를 관리해야 한다.
- 이러한 경우, 이를 단순히 하나씩 순차적으로 처리한다면 매우 비효율적일 것이다.
- 그렇다고 이를 각각의 스레드로 처리한다면, 스레드의 수가 너무 많아질 것이다.
- 이는 스레드의 생성, 종료, 스케줄링 등의 오버헤드를 발생시킬 것이기 때문이다.
6.4.3 상대방이 아닌 내가 전화하게 만들기
- 응용프로그램이 매번 커널에 요청을 보내는 것은 비효율적이므로, 커널이 응용프로그램에게 알림을 보내는 방식이 더 효율적이다.
- 이를 통해 응용 프로그램은 매번 커널에 요청을 보내어 확인하지 않아도 된다.
6.4.4 입출력 다중화
- 멀티플렉싱(multiplexing; MUX)은 여러 개의 입력을 하나의 출력으로 합치는 것을 의미한다.
- 디멀티플렉싱(demultiplexing; DEMUX)은 하나의 입력을 여러 개의 출력으로 분리하는 것을 의미한다.
- 멀티플렉싱의 과정
- 파일 디스크립터를 획득한다.
- 커널에게 이 파일 디스크립터를 관찰하도록 요청한다.
- 커널은 이 파일 디스크립터에 쓸 준비가 되었는지 확인하고, 준비가 되었다면 이를 알린다.
6.4.5 삼총사: select, poll, epoll
- select, poll, epoll은 모두 입출력 다중화를 위한 시스템 콜이다.
- select
- 가장 오래된 방식으로, 모든 파일 디스크립터를 순회하며 확인한다.
- 최대 1024개의 파일 디스크립터를 관찰할 수 있다.
- poll
- select의 개선된 버전으로, 1024개 이상의 파일 디스크립터를 관찰할 수 있다.
- 그러나 여전히 파일 디스크립터가 늘어날 수록 성능이 떨어진다.
- epoll
- 리눅스에서 제공하는 가장 최신의 방식으로, 파일 디스크립터의 수에 관계없이 빠르게 처리할 수 있다.
- 별도의 데이터 구조를 사용하며, 이를 통해 빠르게 처리할 수 있다.
- 특정 파일 디스크립터에 이벤트가 발생하면 요청한 프로세스를 깨우고, 해당 파일 디스크립터를 준비 완료 목록에 추가한다.