반응형
  • 멀티프로세스 서버의 단점

- 프로세스를 생성하는 경우 많은 양의 연산이 요구되며 필요한 메모리 공간도 큼

- 프로세스마다 별도의 메모리 공간을 유지하므로 상호간의 데이터를 송수신하기 우해서는 IPC같은 복잡한 통신방법을 이용해야 함

  • 멀티플렉싱

: 하나의 통신채널을 통해서 둘 이상의 데이터를 전송하는데 사용되는 기술

: 물리적 장치의 효율성을 높이기 위해 최소한의 물리적 요소만 사용해 최대한의 데이터를 전달하기 위해 사용되는 기술

- 시분할 멀티플렉싱 기술

- 주파수 분할 멀티플렉싱 기술

 

  • 멀티플렉싱의 개념을 서버에 적용하기

- 서버에 멀티플렉싱 기술을 도입해 필요한 프로세스의 수를 줄일 수 있음

- 접속해있는 클라이언트의 수에 상관없이 서비스를 제공하는 프로세스의 수는 하나임

멀티프로세스 서버 모델


멀티플렉싱 서버 모델

 

반응형
반응형
  • 메시지를 저장하는 형태의 에코 서버

- 별도의 프로세스에서 클라이언트에게 서비스를 제공하는 프로세스로부터 문자열 정보를 수신받아 클라이언트가 전송하는 문자열을 전달되는 순서대로 파일에 저장

- 파일에 데이터가 어느정도 차면 파일을 닫도록 함

 

// 실행창

- 파이프를 생성한 뒤에 자식 프로세스를 복사시켜 파일의 데이터 저장을 담당

 

반응형
반응형

- fork함수를 통해 생성된 프로세스들은 서로 메모리를 공유하고 있지 않으므로 프로세스간 통신은 별도의 방법을 통해야 함

 

  • 파이프(PIPE) 기반의 프로세스간 통신

PIPE 기반 프로세스 통신 모델

  • 운영체제에 속하는 자원인 PIPE 생성

- 운영체제가 마련한 메모리 공간을 통해 프로세스간 통신 

#include <unistd.h>
int pipe(int fd[2]);
→ 성공 시 0, 실패 시 -1 반환

- fd[0]: 파이프로부터 데이터를 수신하는데 사용되는 file descriptor가 저장 (파이프의 출구)

- fd[1]: 파이프로 데이터를 전송하는데 사용되는 file descriptor가 저장 (파이프의 입구)

 

// 실행창

- 자식 프로세스와 부모 프로세스에서 파이프의 file descriptor가 복사되어 공유

- 자식 프로세스는 입력 경로만, 부모는 출력 경로에만 접근하여 통신

 

  • 파이프(PIPE) 기반의 프로세스간 양방향 통신

- 하나의 파이프를 통한 두 프로세스의 양방향 데이터 통신 방식

- 파이프의 in은 부모 프로세스의 출력도 되고 자식 프로세스의 출력도 됨

- 파이프의 out은 부모 프로세스로의 입력도 되고 자식 프로세스로의 입력도 됨

// 실행창

- 부모 프로세스 영역에서는 부모 프로세스가 종료되기 전에 자식 프로세스 영역을 다 실행할 수 있도록 sleep함수 호출

- 파이프의 file descriptor에 의해 입력된 데이터는 file descriptor를 통해 먼저 읽은 프로세스에게 전달

- 따라서 양방향 프로세스간 데이터 송수신을 위해서는 파이프를 2개 생성하는 방식이 쉬움


- 두 개의 파이프를 통한 두 프로세스의 양방향 데이터 통신 방식

- 서로의 프로세스와 통신하는 파이프의 출력 file descriptor를 프로세스 당 하나씩, 파이프의 입력 file descriptor를 프로세스 당 하나씩

- 하나의 프로세스에서는 파이프의 입력 또는 출력 중 하나만 사용하여 2개의 파이프로 프로세스간 입출력 실행

// 실행창

- fd1: child에서는 입력만 -> parent에서 출력만

- fd2: parent에서 입력만 -> child에서 출력만

반응형
반응형
  • 입출력 루틴 분할의 의미와 이점

- 에코 클라이언트의 경우 하나의 프로세스 안에서 read, write함수를 반복하는 구조이므로 데이터를 송신하면 수신이 완료될때까지 기다려야 했다.

- 입출력 루틴 분할: 데이터의 송신과 수신을 둘 이상의 프로세스로 분할

에코 클라이언트의 입출력 루틴 분리 모델

- 부모 프로세스: 수신

- 자식 프로세스: 송신

- 송신, 수신을 하는 프로세스가 다르므로 데이터의 수신여부와 관계없이 데이터를 전송할 수 있다.

 

  • 이점: 프로그램의 구현이 수월해짐 (부모 프로세스는 수신관련 코드, 자식 프로세스는 송신관련 코드)
  • : 데이터의 수신여부에 상관없이 데이터 전송이 가능하므로 연속된 데이터의 전송이 가능해 데이터의 전송속도가 느린 환경에서 송수신 분량이 더 많음

데이터 송수신 방법의 비교

 

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

- 단, 입출력 루틴 분할된 에코 클라이언트 프로그램의 경우, 수신의 여부와 관계없이 송신이 가능하므로 에코된 메시지의 형태가 잘 보여지도록 printf("input message: "); 문은 제외시킴

- 수신을 담당하는 부모 프로세스에서 좀비 프로세스가 생성되지 않도록 waitpid 함수를 호출시켜 자식 프로세스를 소멸시킴

//실행창

 


◆ 입출력 분리 분할 이후의 EOF 전달

 

  1. file descriptor가 종료되면 EOF가 전달
  2. file descriptor를 완전히 종료하지 않아도 출력 스트림에 대해 종료를 진행하면 EOF가 전달 (shutdown)
  3. file descriptor가 복사되고 나면 복사된 file descriptor까지 모두 종료돼야 EOF가 전달
  4. file descriptor가 복사된 상황이라 할지라도 shutdown 함수호출을 통해 Half-close를 진행하면 상대 호스트로 EOF가 전달

서버

→ 따라서 클라이언트의 자식 프로세스에서 shutdown 함수를 사용하여 출력 스트림을 닫음으로써 EOF를 전달하는 것이 정확한 코드 구현

 

반응형
반응형
  • 프로세스 기반의 다중접속 서버의 구현 모델

- 동시에 둘 이상의 클라이언트에게 서비스를 제공하는 에코 서버

다중접속 서버모델

: 클라이언트의 연결 요청이 있을 때마다 에코 서버는 자식 프로세스를 생성해 클라이언트에게 서비스 제공

 

- 에코서버

: 1단계: 에코 서버(부모 프로세스)는 accept 함수호출을 통해 연결요청을 수락

: 2단계: accept함수를 통해 얻은 file descriptor를 자식 프로세스에게 넘김

: 3단계: 자식 프로세스는 전달받은 file descriptor를 바탕으로 서비스 제공

 

 - 다중 접속 에코 서버의 구현

// 실행창_ 서버

// 실행창_클라이언트_1 (24593)

// 실행창_클라이언트_2 (24601)

- 생성된 자식 프로세스에서 클라이언트에게 에코 서비스를 제공하는데 서버 socket의 file descriptor까지 복사되기 때문에 close

- 부모 프로세스에서는 accept함수를 통해 생성된 socket의 file descriptor를 소멸 (다른 클라이언트의 연결 요청이 있을 경우 accept함수를 통해 socket생성)

- 서버의 부모 프로세스에서 클라이언트의 연결요청을 수락

 

  • fork함수를 통한 file descriptor의 복사

- 부모 프로세스에 저장되어 있던 서버 socket, 클라이언트와 연결된 socket의 file descriptor가 자식 프로세스에 복사

- socket은 부모 프로세스가 아닌 운영체제의 소유이므로 socket이 복사되진 않음 (IP, PORT번호로 할당된 socket은 유일)

- 하나의 socket에 두 개의 file descriptor 할당

fork 함수의 호출과 파일 디스크립터의 복사

- 하나의 socket에 두 개의 file descriptor가 존재하는 경우 두 개의 file descriptor가 모두 소멸되어야 socket이 소멸

- 부모 프로세스에서 클라이언트와 연결된 file descriptor를 소멸하지 않으면 자식 프로세스에서 클라이언트와 연결된 file descriptor를 소멸하려 해도 남아있음

반응형

'프로그래밍의 기초 > TCP | IP' 카테고리의 다른 글

프로세스간 통신의 기본 개념  (0) 2022.01.20
TCP의 입출력 루틴 분할  (0) 2022.01.20
시그널 핸들링  (0) 2022.01.19
프로세스 & 좀비 프로세스  (0) 2022.01.18
프로세스와 스케줄러  (0) 2022.01.18
반응형

- 부모 프로세스에서 waitpid 함수를 계속 호출하여 자식 프로세스가 종료되기를 기다리는 것은 효율적인 방법이 아닐 수 있음

- 시그널 핸들링(signal handling): 자식 프로세스의 종료를 인식하는 운영체제가 부모 프로세스에 자식 프로세스의 종료를 알려야 함

 

 

  • JAVA의 경우 프로세스나 쓰레드의 생성방법을 프로그래밍 언어 차원에서 제공하지만 C, C++ 의 경우 ANSI표준에서 함수를 제공하지 않음 

- 프로세스, 쓰레드의 경우 운영체제 차원에서 지원되는데 JAVA는 플랫폼 독립의 특성을 가지고 있어 운영체제에 상관없이 동일하게 적용되는 프로세스, 쓰레드의 생성방법을 제공

 

  • signal과 signal 함수
  • signal 등록: 부모 프로세스에서 자식 프로세스 종료 시 특정 함수의 호출을 운영체제에게 요구
#include <signal.h>
void (*signal (int sig, void (*func)(int)))(int);
→ signal 발생 시 호출되도록 이전에 등록된 함수의 포인터 반환

- signal(int sig, void(*func)(int)) 함수의 함수 포인터형

- 매개변수가 int, void형을 반환하는 함수 포인터 반환

- sig: 특정 상황에 대한 정보

- void (*func)(int): 특정 상황에서 호출될 함수의 포인터

- sig의 상황 발생 시 func함수 호출

FLAG 의미
SIGALRM alarm 함수호출을 통해서 등록된 시간이 된 상황
SIGINT CTRL+C가 입력된 상황
SIGCHLD 자식 프로세스가 종료된 상황
  • alarm 함수
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
→ 0 또는 SIGALRM signal이 발생하기까지 남아있는 시간을 초 단위로 반환

- 매개변수에 전달된 시간이 지나서 SIGALRM signal이 발생하고 0을 전달하면 이전에 설정된 SIGALRM signal 발생의 예약이 취소

- 위의 함수를 통해서 SIGALRM signal 발생을 예약해놓고 SIGALRM signal이 발생했을 때 호출될 함수를 등록하지 않으면 프로세스가 바로 종료

 

// 실행창

// 실행창

CTRL+C 입력 시 실행창

- 메인 함수에서 시그널의 발생과 핸들러 함수의 호출을 보기 위해 100초간 3번 sleep함수를 호출하고 종료

- signal이 발생하면 시그널 핸들러 함수의 호출을 위해 sleep 함수의 호출로 blocking 상태에 있던 프로세스가 깨어나고 다시 잠들지 않으므로 sleep함수를 반복하여 호출

 

  • sigaction 함수를 이용한 시그널 핸들링

- signal 함수는 유닉스 계열의 운영체제 별로 동작방식에 있어 차이가 있지만 sigaction 함수는 차이를 보이지 않음

#include <signal.h>
int sigaction(int sig, const struct sigaction *__restrict__ new, struct sigaction *__restrict__ old);
→ 성공 시 0, 실패 시 -1 반환

- sig: signal의 정보

- _restrict_new: 매개변수로 전달된 signal 발생 시 호출될 함수

- _restrict_old: 이전에 등록되었던 signal 핸들러의 함수 포인터를 얻는데 사용되는 인자, 필요없다면 0

 

struct sigaction {
void (*sa_handler)(int);            // 시그널 핸들러의 함수 포인터값
sigset_t sa_mask;                   
int sa_flags;                          
void (*sa_sigaction)(int, siginfo_t *, void *);     
};

- sa_mask, sa_flags(signal관련 옵션 및 특성의 지정)은 모든 비트를 0으로 초기화

 

// 실행창

 

  • signal handling을 통한 좀비 프로세스의 소멸

// 실행창

- 2개의 자식 프로세스를 생성한뒤 2번의 시그널을 통한 시그널 핸들러 함수(자식 프로세스 소멸) 호출을 위해 부모 프로세스에서 적어도 2번의 sleep함수 호출해야함

반응형

'프로그래밍의 기초 > TCP | IP' 카테고리의 다른 글

TCP의 입출력 루틴 분할  (0) 2022.01.20
멀티태스킹 기반의 다중접속 서버  (0) 2022.01.19
프로세스 & 좀비 프로세스  (0) 2022.01.18
프로세스와 스케줄러  (0) 2022.01.18
CreateProcess 함수  (0) 2022.01.17

+ Recent posts