본문 바로가기

임베디드 리눅스

네트워크 프로그래밍 - 다중 접속 서버 구현을 위한 기초 (feat. 프로세스, fork(), 좀비 프로세스 )

728x90
반응형

안녕하세. WH 입니다.

피곤한 월요일이네요. 저만 그럴까요? ㅎㅎ 그건 그거고 여튼 시작해 보겠습니다.

네트워크 프로그래밍이 반응이 좋아서

다중 접속 서버 구현을 한번 해볼까합니다.

대표적으로 3가지 방법이 있는데요.

멀티 프로세스, 멀티 플렉싱, 멀티 쓰레드 방법이 있습니다.

가장 먼저 멀티 프로세스 방법에 대해 알아보겠습니다.

 

멀티 프로세스 기반 서버 

  다수의 프로세스를 생성하는 방식으로 서버를 구현하는 방법입니다. 모든 프로세스는 운영체제로부터 ID를 부여 받습니다. 그리고 이 ID 를 프로세스 ID라 부르고 2 이상의 정수를 가진답니다. 1은 어디갔냐구요? 운영체제 실행을 돕는 프로세스에게 할당된답니다. 제가 이제까지 이야기하고 있던 환경은 리눅스 우분투였죠? 실행 중인 프로세스를 확인하는 방법은 ps au 입니다. 이걸 왜 확인하냐구요? 우리가 지금까지 설명하던 PID( 프로세스 ID )를 확인하려구요. 왜요? 이제부터 프로세스를 복사할꺼라서요.

 

fork 함수 호출을 통한 프로세스 생성

  fork 함수는 호출한 프로세스의 복사본을 생성한답니다. 이 말이 무슨 말이다? 새로운 다른 프로그램에서 생성하는 게 아니라, 실행중인 fork 함수를 호출한 프로세스를 복사한다는 점입니다. 또한 기억해야할 점은 두 프로세스 모두 fork 함수 호출 이후 문장을 실행한다는 점입니다. 그런데 메모리 영역까지 완벽하게 같기 복사하기 때문에 이후의 프로그램 흐름은 fokr 함수의 반환 값을 기준으로 나뉘도록 프로그래밍을 해야한답니다. 용어 하나만 정리하고 갈게요. 부모 프로세스와 자식 프로세스 인데요. 부모 프로세스는 원본 프로세스, 즉 fork() 를 호출한 주체를 뜻하며, 자식 프로세스는 부모 프로세스의 fork() 를 통해 복사된 프로세스를 의미합니다.

 

fork 함수의 반환 값

부모 프로세스에서의 fork() 반환 값 : 자식프로세스 ID

자식 프로세스에서의 fork() 반환 값 : 0

 

아래 그림을 통해 복사 시점과 실행 부분을 주목해서 봐주세요

 

반응형

프로세스 & 좀비 프로세스

  할당과 반납은 컴퓨터 자원 관리에서 굉장히 중요한 일입니다. 할당과 반납, 생성과 소멸을 제대로 해주지 않는다면, 떄로는 시스템을 터트리기도 한답니다. 대표적으로 메모리 누수, 좀비 프로세스 등이 있죠. 좀비 프로 세스란, 생성 후 main 함수의 실행이 완료 되면 사라져야 하는데 사라지지 않고 시스템의 중요한 용량을 차지하는 프로세스를 말합니다. 왜 좀비 프로세스가 생기는 것일까요? 그 이유는 main 함수의 return 값이나 exit 함수로 전달되는 인자 값이 모두 운영체제로 전달됩니다. 그리고 운영체제는 전달 받은 값을 부모 프로세스로 전달하기 전까지 자식 프로세스를 종료하지 않죠.

 

   그럼 좀비 프로세스는 운영체제가 부모 프로세스에 값만 전달해주면, 문제는 해결되겠네요? 맞아요. 그런데 운영체제는 값을 알아서 전달해 주지 않아요. 부모 프로세스가 함수 호출을 통한 요청이 있어야 운영체제로 부터 그 값을 받을 수 있죠.

 

좀비 프로세스의 소멸시키기

   자, 부모 프로세스가 자식 프로세스의 전달 값만 받으면 됩니다.  먼저, wait 이라는 함수가 있어요

#include <sys/wait.h>
pid_t sait(int *statloc); // 성공 시 종료된 자식 프로세스의 ID, 실패 시 -1

이 함수는 이미 종료된 자식 프로세스가 종료하며 값을 남기죠? 그 값의 주소를 전달인자로 넘기는 함수에요. 그 값을 가지고 뭘 반환한다고요? 성공하면 자식의 PID를 반환한다구요. 그런데 주의할 점 역시 하나 존재한답니다. 무엇이냐면, 만약 종료된 자식 프로세스가 없다면, 종료된 자식 프로세가 있을 때 까지 블로킹상태에 놓인다는 특징을 가져요. wait 함수는 매크로 함수와 세트로 쓰이는 데요. 

 

- WIFEXITED : 자식 프로세스가 정상 종료한 경우 '참(true)'을 반환

- WEXITSTATUS : 자식 프로세스의 전달 값을 반환

 

wait 함수와 두 가지 매크로 함수는 set로 활용된답니다. 한글로 먼저 보면, 이런 느낌이죠.

 

프로세스가 종료되서 pid를 받았어(wiat) 근데 if 정상 종료(WIFEXITED) 됐어? 그럼 반환 값이 뭔데(WEXITSTATUS)?

코드는 아래와 같은 느낌이에요

int status;

wait (&status);
if(WIFEXITED(status)
    printf(" value : %d\n", WEXITSTATUS(status))

 

그 다음으로는 waitpid 함수가 있어요 wait 함수와 차이는 블로킹 문제가 발생하지 않는다는 점이죠.

#include <sys/wait.h>
/* 성공 시 종료된 자식 프로세스의 ID( 또는 0 ), 실패 시 -1 반환 */
pid_t waitpid(pid_t pid, int * statloc, int options);

인자를 살짝 들여다 볼까요?

 

  - pid : 종료를 확인하고자하는 자식 pid 전달, if -1을 전달하면 wait 함수처럼 자식 프로세스가 종료되기를 기다림
  - tatloc : wait 함수의 매개변수 statloc과 동일한 의미( 자식 프로세스가 종료하며 전달하는 값의 주소 )
  - options : WNOHANG을 인자로 전달시 종료된 자식 프로세스가 없더라도 블로킹 상태에 있지 않고, 0을 반환

 

이거 다 어따 써먹어요? 곧 써먹어요. 그니까 조금만 기다려주세요. 오늘은 여기까지 하겠습니다. 이상 WH 였습니다.

 

 

728x90
반응형