일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 신경망 학습
- 설정
- BOJ
- Python
- Mac
- 파이싼
- 밑바닥부터 시작하는 딥러닝
- 손실함수
- 가상환경
- 개발환경
- 4948
- 실버
- 15649
- streamlit
- 1101
- N-Queen
- 재귀
- 그리디 알고리즘
- 백준
- 경사하강법
- pyenv
- 백트래킹
- 파이썬
- end to end
- 기계학습
- n과 m
- 9020
- 1002
- Today
- Total
파이톨치
[socket programming] 멀티 프로세스 기반 다중 서버 본문
멀티 프로세스
다중 접속 서버
둘 이상의 클라이언트에게 동시에 접속을 허용하여, 동시에 둘 이상의 클라이언트에게 서비스를 제공하는 서버를 의미한다.
프로세스
실행 중인 프로그램에 관련된 메모리, 리소스 등을 총칭하는 의미, 멀티프로세스 운영체제는 둘 이상의 프로세스를 동시에 생성가능. 운영제제는 생성되는 모든 프로세스에 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_flags는 0으로 초기화! 이 둘은 시그널 관련 정보의 추가 전달에 사용되는데, 좀비의 소멸을 목적으로는 사용되지 않는다.
시그널 핸들링을 통한 좀비 프로세스의 소멸
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);
구현의 용이성에도 좋은점수를 줄 수 있다. 물론, 인터랙티브 방식의 데이터 송수신을 진행하는 경우에는 이러한 분할이 큰의미를 부여하지 못한다. 즉, 이러한 형태의 구현이 어울리는 상황이 있고, 또 어울리지 않는 상황도 있다.
'대학수업 > socket programming' 카테고리의 다른 글
[socket programming] 멀티 쓰레드 기반의 서버 구현 (1) | 2024.04.20 |
---|---|
[socket programming] IO multiplexing (1) | 2024.04.20 |
[socket programming] Socket Options (2) | 2024.04.19 |
[socket programming] UDP socket program (1) | 2024.04.19 |
[sock programming] Loopback "hello world" (2) | 2024.04.02 |