Multi-connection Server
- 서버는 connection 요청을 보내온 모든 client와 동시에 서비스 해야함
- Multiplexing-based server: 입출력 대상을 grouping하여 서비스
- Multiprocess-based server: 다중 프로세스로 서비스
- Multi-threading-based server: client 수만큼 스레드 만들어서 서비스
fork()
#include <unistd.h>
pid_t fork()
- 새로운 프로세스를 생성하는 함수
- fork()를 호출한 프로세스가 복사됨
- fork() 호출 이후로 각 프로세스는 독립적으로 실행
- 리턴값
- 성공 부모 프로세스라면: 자식 프로세스의 pid 자식 프로세스라면: 0
- 실패: -1
자식 프로세스가 터지면? - wait()
- 자식 프로세스가 terminate되면 부모 프로세스에게도 정보가 전달됨
#include <sys/wait.h>
pid_t wait(int *status)
- 부모 프로세스가 자식 프로세스의 변화를 모니터링하는 함수
- 자식 프로세스가 종료될 때까지 blocking 상태로 기다림
- status: 자식 프로세스의 status가 저장됨
- WIFEXITED(status): child 끝나면 return true
- WEXITSTATUS(status)
- WIFSIGNALED(status)
- 리턴값: 자식 프로세스의 pid
- pid_t pid = fork(); 자식 프로세스 실행 시작
- else if문: fork에서 error 가 발생한 경우
- wait(&status): 자식 프로세스가 끝나길 기다림. 모니터링 중 → 자식 프로세스가 좀비 프로세스가 되지 않도록 함.
waitpid()
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
- pid: wait할 특정 자식 프로세스의 pid or 0, -1 등 특정 값
- -1: 임의의 자식 프로세스를 기다림
- 0: waitpid를 호출한 프로세스의 프로세스 그룹id와 같은 프로세스 그룹id를 가진 프로세스를 기다림
- -1보다 작은 경우
- status: 자식 프로세스의 status가 저장될 포인터
- options: waitpid()의 동작을 결정
- WNOHANG: wait하고 있는 pid가 종료되지 않아서 즉시 종료 상태를 회수할 수 없는 경우, 호출자는 blocking 되지 않고 0을 return 받음
멀티프로세스 구현 코드
IPC (Inter Process Communication)
- OS에 의해 프로세스 간 데이터를 공유하는 매커니즘
- Pipes
- Named Pipes
- Message Queues
- Semaphores
- Shared Memory
- Sockets
Signal
- 주로 UNIX, UNIX계열, POSIX 운영체제에서 사용되는 제한된 형태의 IPC 방법
- 운영 체제 내의 프로세스 사이에서 이벤트를 알리기 위해 사용됨
- 비동기적: signal은 프로세스에게 비동기적으로 전달됨 == 프로세스가 언제든지 signal을 받을 수 있음
- signal을 통해 프로세스를 중지, 종료, 특정 작업을 수행하도록 제어할 수 있음
- signal마다 고유 번호를 가짐 (kill -l 명령어로 확인 가능)
#include <signal.h>
void (*signal(int sig, void(*func)(int)))(int);
- sig: signal의 고유 번호
- func: signal이 들어왔을 때 수행할 함수를 가리키는 포인터
- SIG_IGN: signal이 들어오면 무시함
- SIG_DFL: signal이 들어오면 default operation을 수행함
- 리턴값
- 수행한 func의 가장 최근 값
좀비 프로세스
main 함수가 끝났는대도 사라지지 않고 시스템에서 자원을 차지하고 있는 프로세스를 의미
자식 프로세스가 종료되는 과정
- fork()로 생성한 자식 프로세스는 종료될 때 exit()을 호출하여 자신의 인자를 전달하고 운영 체제에게 알림
- 또는 자식 프로세스의 main 함수에서 return문을 실행하면서 OS에게 return 값을 전달함
좀비 프로세스 발생 원인, 방지 방법
위 두 경우 모두 return 값이 운영 체제에게 전달되지만, 운영 체제는 이 값을 부모 프로세스에게 전달할 때까지 자식 프로세스를 완전히 소멸시키지 않는다. 이렇게 자식 프로세스는 종료되기 위해 return 값을 OS에게 전달했지만 아직 부모 프로세스에게 return 값을 전달하지 못해서 자식 프로세스가 완전히 소멸되지 않은 상태가 좀비 프로세스이다. 보통 자식 프로세스가 return 되었지만 부모 프로세스가 자식 프로세스의 return 값을 회수하지 못한 경우에 발생한다. 이를 방지하기 위해 부모 프로세스는 wait(), waitpid()를 사용하여 자식 프로세스의 종료 상태를 모니터링해야 한다.
- OS는 자식 프로세스로부터 전달된 return 값을 능동적으로 처리하지 못함
- 이 값은 부모 프로세스가 wait()으로 회수해야만 처리됨
sigaction()
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
- signum: 설정하거나 쿼리하려는 signal의 고유 번호
- act: signal number에 대한 새로운 동작을 지정하는 sigaction 구조체에 대한 포인터
- oldact: signal에 대해 이전에 설정된 sigaction 구조체를 저장할 포인터
- return value
- 성공: 0
- 실패: -1
'CS > Network' 카테고리의 다른 글
06_Multiplexing (1) | 2024.07.24 |
---|---|
05_Thread (12) | 2024.07.24 |
03_TCP Connections (0) | 2024.07.24 |
02_Socket_IO (2) | 2024.07.23 |
TCP flow control이란? (0) | 2024.03.18 |