#9 리눅스(유닉스) 프로세스 관리

HYUN·2021년 6월 14일
0
post-thumbnail

프로그램 | 프로세스 | 스레드

  • 프로그램: 바이너리, 코드 이미지, 응용 프로그램, Application, 실행 파일
  • 프로세스: 메모리에(로드 및 프로세스 상태 정보 포함"PCB") 실행 중인 프로그램
  • 스레드: 리눅스에서는 프로세스가 생성되면 스레드도 생성이 되며 보통 기본 프로세스(싱글 스레드 프로세스)이며 다중 스레드(멀티 스레드 프로세스)를 사용할 수도 있습니다.

프로세스 ID | pid

각 프로세스는 고유한 pid를 가지게 되며 최대 값은 2^15 = 32768이고 부호형(signed) 16비트 정수값을 사용합니다.

프로세스 계층

  • 최초 프로세스: init 프로세스, pid 1
  • init 프로세스는 운영체제가 생성
  • 다른 프로세스는 또 다른 프로세스로 부터 생성 (부모 프로세스, 자식 프로세스)
  • ppid 값이 부모 프로세스의 pid를 뜻함

프로세스와 소유자 관리

  • 리눅스 내부에서는 프로세스의 소유자와 그룹을 UID/GID(정수)로 관리
  • 사용자에 보여줄때에만 UID와 사용자 이름 매핑 정보를 기반으로 사용자 이름으로 제공

getpid() | getppid

#include <sys/types.h>
#include <unistd.h>
pid_t getpid (void);
pid_t getppid (void);

프로세스 생성

프로세스의 5가지 구조
CODE, DATA, BSS, HEAP, STACK

기본 프로세스 생성 과정

  1. CODE, DATA, BSS, HEAP, STACK의 공간을 생성
  2. 프로세스 이미지를 해당 공간에 업로드하고, 실행 시작

프로세스 계층: 다른 프로세스는 또 다른 프로세스로부터 생성

  • 부모 프로세스, 자식 프로세스

fork()와 exec() 시스템콜

fork() 시스템 콜

헤더 파일: <unistd.h>
함수 원형: pid_t fork(void);
  • pid = fork()가 실행되면 부모 프로세스와 동일한 자식 프로세스가 별도 메모리 공간에 생성
  • 자식 프로세스는 pid가 0으로 리턴, 부모 프로세스는 실제 pid 리턴
  • 두 프로세스의 변수 및 PC(Program Counter) 값은 동일
  • 새로운 프로세스 공간을 별도로 만들고, fork() 시스템 콜을 호출한 프로세스(부모) 공간을 모두 복사한 후, fork() 시스템 콜 이후 코드부터 실행
  • 새로운 프로세스 공간을 별도로 만들고, fork() 시스템 콜을 호출한 프로세스(부모) 공간을 모두 복사 | 별도의 프로세스 공간을 만들고, 부모 프로세스 공간의 데이터를 그대로 복사

exec() 시스템 콜

헤더 파일: <unistd.h>
함수 원형
int execl (const char *path, const char *arg, ...);
int execlp (const char *file, const char *arg, ...);
int execle (const char *path, const char *arg, ..., char * const envp[]);
int execv (const char *path, char *const argv[]);
int exevp (const char *file, char *const argv[]);
int exevpe (const char *file, char *const argv[], char *const envp[]);
  • exec() 시스템 콜을 호출한 현재 프로세스 공간의 CODE, DATA, BSS 영역을 새로운 프로세스의 이미지로 덮어씌움 | 별도의 프로세스 공간을 만들지 않음

wait() 시스템 콜

  • wait() 함수를 사용하면, fork() 함수 호출시, 자식 프로세스가 종료할 때까지, 부모 프로세스가 기다린다.
  • 자식 프로세스와 부모 프로세스의 동기화, 부모 프로세스가 자식 프로세스보다 먼저 죽는 경우를 막기 위해 사용(고아 or 좀비 프로세스)

copy-on-write

  • fork()는 새로운 프로세스 공간 생성 후, 기존 프로세스의 공간을 복사한다.
    즉, 4GB를 복사한다면 프로세스 생성 시간이 오래걸린다.

자식 프로세스 생성시, 부모 프로세스 페이지를 우선 사용
부모 혹은 자식 프로세스가 해당 페이지를 읽기가 아닌, 쓰기를 할 때 페이지를 복사하고, 분리함
덕분에 프로세스 생성 시간을 줄일 수 있고 새로 생성된 프로세스에 새롭게 할당되어야 하는 페이지 수도 최소화할 수 있다.

exit() 시스템 콜

프로세스 종료 시스템 콜
부모 프로세스는 status & 0377 계산 값으로 자식 프로세스 종료 상태 확인 가능

#include <stdlib.h>
void exit(int status);

주요동작

  • atexit()에 등록된 함수 실행
  • 열려 있는 모든 입출력 스트림 버퍼 삭제
  • 프로세스가 오픈한 파일을 모두 닫음
  • tmpfile() 함수를 통해 생성한 임시 파일 삭제
    • tmpfile() - 임시 파일을 wb+ (쓸 수 있는 이진파일 형태) 모드로 오픈 가능

atexit() 함수

프로세스 종료시 실행될 함수를 등록하기 위해 사용
등록된 함수를 등록된 역순서대로 실행

main 함수의 return 0; 과 exit(0)의 차이

  • exit() 함수 : 즉시 프로세스를 종료한다. exit() 함수 다음에 있는 코드는 실행되지 않는다.
  • return 0; : 단지 main() 이라는 함수를 종료한다.
    • 단, main()에서 return 시, C언어 실행 파일에 기본으로 포함된 _start() 함수를 호출하게 되고, 해당 함수는 결국 exit() 함수를 호출한다.

main() 함수에서 return 0; 은 exit() 호출과 큰 차이가 없다.








profile
자바스크립트를 좋아합니다. | 이유를 알고 있는 것과 모르는 것의 차이는 분명하다.

0개의 댓글