본문 바로가기
네트워크, 서버/IOModel

(IOModel)멀티플렉싱 - select

by 흥부와놀자 2020. 10. 5.

멀티플렉싱이란?

여러명이서 통신할때 하나의 채널만 가지고 통신하는 방식을 말한다. 멀티쓰레드, 멀티 프로세스가 여러 채널을 만들어 통신한다면 멀티플렉싱은 하나의 프로세스, 스레드를 가지고 여러 명의 통신을 연결시킨다.

 

여러명이 접속할 수 있는 서버를 만들기 위해 여러 IO모델들이 사용된다. 오늘은 대표적인 멀티플렉싱 방식의 IO 모델인 select에 대해 살펴보고자 한다.

 

1. select 동작 과정

서버는 여러 클라이언트의 접속을 받는다. 그 후 각 클라이언트의 이벤트(데이터 수신여부, 데이터 송신가능 여부, 오류 수신 여부 등)의 이벤트가 들어옴에 따라 해당 클라이언트에게 적절한 응답을 해줘야 한다.

 

select의 경우 먼저 FD_SET이라는 구조체를 통해 클라이언트들을 등록시킨다. 

FD_SET

해당 구조체는 Linux의 경우 해당 소켓의 파일디스크립터 번호의 배열로 되어있고 윈도우의 경우 소켓의 핸들번호의 배열로 되어 있다. 구조체 관리함수는 FD_ZERO(모두 등록안됨으로 초기화) , FD_SET(해당 소켓 등록), FD_CLR(해당 소켓을 등록에서 제거), FD_ISSET(해당 소켓이 등록됬는지 확인)가 있다.

 

이러한 FD_SET에 들어온 클라이언트의 소켓을 등록했다면 이제 select함수를 호출해 줘야 한다. 

select(파일 디스크립터 개수, 수신한 데이터가 있는 FD_SET , 송신 가능한 FD_SET, 예외발생한 FD_SET, TimeOut)을 통해 호출한다.

위에 각 이벤트 자리에 FD_SET을 인수로 등록 시키는 것은 FD_SET안에 있는 소켓들 중 해당된 이벤트가 있는지 감시하기 위한 용도로 등록시키는 것이다.

주의점은 위의 select함수에 들어간 FD_SET들이 변화된 결과(만약 수신데이터 자리에 넣어졌다면 해당 FD_SET에 수신된 데이터가 있는 소켓 자리만 1로 바뀐다.)로 초기화 되기 때문에 감시할 대상이 있는 FD_SET과 이벤트 결과가 들어갈 FD_SET을 따로 구분지어 매 루프마다(이벤트 결과를 처리한 후 마다) 감시할 대상이 있는 FD_SET을 결과 FD_SET에 복사 시켜줘야 한다는 것이다.

 

timeout자리에 timeval 구조체가 들어가고 시간을 설정할 수 있는데 NULL이면 FD에 변화가 생길때까지 계속 블로킹되고 시간이 설정되면 해당 시간동안 기다린 뒤 0을 반환한다. 해당 select가 반환하는 정수값은 변화된 파일디스크립터의 개수를 의미한다.

 

2. 장단점

가장 큰 장점은 멀티스레드, 멀티프로세스와 다르게 교착상태, 레이스 컨디션을 피하고 하나의 스레드에서 안정적으로 처리 가능하다는 점이다.

 

단점은 다른 IO모델과 비교하여 성능상 많은 접속을 받지 못한다. 그것엔 두가지 이유가 있는데 첫번째는 매순간 감시하고자 하는 FD_SET을 복사하여 select를 호출하는 것이다. 이 과정에서 해당 FD_SET이 커널로 넘어가게 되고 부하가 된다. 

 

두번쨰는 내부에서 변경된 FD을 찾기위해 FD_SET을 도는 것이다. 접속자가 많아질 수록 부하가 심해진다.

이러한 이유로 인해 많은 접속이 필요한 곳엔 select를 쓸수가 없다. 하지만 많은 접속이 필요하지 않는 경우엔 select를 통해 하나의 프로세스와 스레드로 최소한의 자원사용률과 안정적으로 이벤트를 처리할 수 있다.

 

'네트워크, 서버 > IOModel' 카테고리의 다른 글

(IOModel)Epoll  (0) 2020.10.05