파이톨치

[socket programming] 멀티 프로세스 기반 다중 서버 본문

대학수업/socket programming

[socket programming] 멀티 프로세스 기반 다중 서버

파이톨치 2024. 4. 19. 20:38
728x90

멀티 프로세스

다중 접속 서버

이상의 클라이언트에게 동시에 접속을 허용하여, 동시에 이상의 클라이언트에게 서비스를 제공하는 서버를 의미한다.

 

프로세스

실행 중인 프로그램관련된 메모리, 리소스 등을 총칭하는 의미, 멀티프로세스 운영체제는 이상의 프로세스를 동시에 생성가능. 운영제제생성되는 모든 프로세스에 ID할당(PID)

 

fork 함수

fork 함수가 호출되면, 호출한 프로세스가 복사되어 fork 함수호출 이후를 각각의 프로세스가 독립적으로 실행

fork 함수 호출 이후의 반환 값의 차를 통해서 부모프로세스와 자식프로세스의 프로그램 흐름을 구분하게 된다, 

fork 함수를 호출한 프로세스는 부모 프로세스이고 반환값은 자식의 PID이며, fork 함수의 호출을 통해서 생성된 프로세스는 자식 프로세스, 반환값은 0이다. 실행은 자식이 먼저이다.

 


좀비프로세스

실행이 완료 되었음에도 불구 하고, 소멸되지 않은 프로세스. 소멸되지 않았다는 것은 프로세스가 사용한 리소스가 메모리 공간에 여전히 존재한다는 의미. 자식 프로세스가 종료되면서 반환하는 상태값이 부모 프로세스에게 전달되지 않으면 프로세스는 소멸되지 않고 좀비가 된다

 

exit 호출, main 함수 return 실행 -> 자식 프로세스의 종료 상태값이 운영체제에 전달되는 경로 

자식 프로세스의 종료값을 반환 받을 부모 프로세스가 소멸되면, 좀비의 상태로 있던 자식프로세스도 함께 소멸되기 때문에 부모 프로세스가 소멸되기 전좀비의 생성을 확인해야 한다

 

wait 함수

wait 함수의 경우 자식 프로세스가 종료되지 않은 상황에서반환하지 않고 블로킹 상태에 놓인다특징있다

WIFEXITED 자식 프로세스가 정상 종료한 경우 ‘참(true)’반환한다. WIFEXITED(status) 

WEXITSTATUS 저장된 종료 상태 코드를 반환한다. WEXITSTATUS(status)  

 

 

waitpid 함수

wait 함수는 블로킹상태에 빠질 있는 반면, waitpid 함수는 블로킹 상태에 놓이지 않게 끔 있다는 장점있다

waitpid 함수 호출번째 인자로 -1, 번째 인자로 WNOHANG전달 되었으, 임의의 프로세스가 소멸되기를 기다리, 종료된 자식 프로세스가 없으면 0하면서 함수를 빠져나온다. 자식 프로세스의 상태 변화를 기다리지 않고 바로 제어를 반환받는다. 이 함수를 사용하면 자식 프로세스의 상태를 비동기적으로 확인한다. 자식 프로세스가 종료되었는지 주기적으로 확인하거나, 시그널 핸들러에서 자식 프로세스의 종료를 처리할 때 유용하게 사용한다. 

waitpid(-1, &status, WNOHANG); 


시그널 핸들링

시그널

특정 상황되었을운영체제가 프로세스에게 해당 상황이 발생 했음을 알리는 일종의 메시지가리켜 시그널이라 한다.

 

시그널등록

특정상황에서 운영체제로부터 프로세스가 시그널을 받기 위해서는 해당상황에 대해서 등록의 과정

시그널등록되면, 함께 등록된 함수의 호출을 통해서 운영체제는 시그널의 발생을 알린다.

 

signal(SIGCHLD, mychild); 자식프로세스가 종료되면 mychild 함수를 호출해달라

signal(SIGALRM, timeout); alarm 함수 호출통해서 등록된 시간이 지나면 timeout 함수 호출

signal(SIGINT, keycontrol); CTRL+C입력되면 keycontrol 함수를호출해달라

 

시그널 핸들링 예제

signal 함수는 운영체제 별로 동작 방식의 차이보이기 때문에 이어서 설명하는 sigaction 수를 대신 용한다. signal 함수는 과거 프로그램과의 환성을 유지하기 위해서 제공.

시그널이 발생하면, sleep 함수의 호출을 통해서 블로킹 상태에 있던 프로세스가 깨어난다. 그래서 예제의 경우 코드의 내용대로 300초의 sleep 시간을 갖지 않는다.

 

sigaction 함수

sigaction 구조체 변수를 선언해서, 시그널 등록호출될 함수의 정보를 채워서 위의 함수 호출인자로 전달한다. sa_mask모든 비트는 0, sa_flags0으로 초기화! 둘은 시그널 관련 정보의 추가 전달사용되는데, 좀비의 소멸을 목적으로는 사용되지 않는다.

 

시그널 핸들링을 통한 좀비 프로세스의 소멸

SIGCHID(자식 프로세스가 종료하면 발생하는 signal)대해서 시그널 핸들링을 등록하였으니, 등록된 함수 내에서 좀비를 소멸하면 좀비프로세스는 생성되지 않는다. 


멀티태스킹기반

프로세스 기반 다중접속 서버 모델

핵심은 연결이 하나 생성될 때마다 프로세스를 생성해서 해당 클라이언트에 서비스를 제공하는 것이다.

 

fork 함수 호출을 통한 디스크립터의 복사

프로세스가 복사되는 경우 해당 프로세스에 의해 들어진 소켓이 복사되는아니고, 파일 디스크립터복사되어 왼쪽 그림의 형태가 된다.

하나의 소켓에 개의 파일 디스크립터가 존재하는 경우, 파일 디스크립터 모두 종료되어야 해당 소멸된다. 그래서 fork 함수 호출 후에는 서로에게 상관없는 파일디스크립터를  종료한다. 자식은 서버 소켓 파일 디스크립터 종료하고, 부모는 클라이언트 소켓 파일 디스크립터 종료한다. 

 

다중접속에코서버의구현

클라이언트와 연결되면 (accept(serv_sock, (struct sockaddr*) &clnt_adr, sizeof(clnt_adr));), 자식 프로세스를 생성해서(pid=fork();), 자식 프로세스가 서비스제공하게 한다 (if(pid==0)). 물론, 좀비 프로세스의 소멸을 위해서 앞서 보인, 좀비의 해결을 위한 함수의 호출과정은 거쳐야 한다. (struct sigaction act; sigaction(SIGCHILD, &act, 0);)


TCP입출력 루틴 분할

입출력 루틴 분할의 이점과 의미

소켓은 양방향 통신이 가능하다. 따라서 왼쪽 그림과 같이 입력을 담당하는 프로세스와 출력담당하는 프로세스를 각각 생성하면, 입력과 출력을 각각 별도로 진행 시킬 있다. 입출력 루틴을 분할하면, 보내고 받는 구조가 아니라, 둘이 동시에 진행 가능하다

 

에코 클라이언트의 입출력 분할의

입력을 담당하는 함수와 출력을 담당하는 함수구분지어 정의했기 때문에

pid = fork();

 if (pid==0)

    write_routine(sock, buf)

else

    read_routine(sock, buf);

구현의 용이성에도 좋은점수를 있다. 물론, 인터랙티브 방식의 데이터 송수신을 진행하는 경우에는 이러한 분할이 의미를 부여하지 못한다. , 이러한 형태의 구현이 어울리상황이 있고, 어울리지 않는 상황도 있다.

 

 

728x90