Skip to content

Latest commit

 

History

History
91 lines (75 loc) · 5.41 KB

File metadata and controls

91 lines (75 loc) · 5.41 KB

fork()를 통한 자식 프로세스 생성

  • fork()로 자식 프로세스 생성 수행.
  • fork()의 리턴값이 0이면 자식 프로세스로 식별.
  • pid = fork()와 같이 리턴값을 저장하여 pid 값에 따라 부모와 자식이 다른 동작을 수행하도록 구성 가능.

좀비 프로세스(Zombie Process) 발생 원인

  • 자식 프로세스 종료 시 부모 프로세스가 상태를 수거하지 않으면 좀비 프로세스가 됨.
  • 자식의 리턴값을 부모 프로세스가 수거해야 하나, sleep() 등의 블로킹 동작 수행 중에는 수거가 불가능함.
  • 부모의 sleep() 동작이 종료되면 리턴값을 수거하여 자식 프로세스가 정상 종료됨.
  • sleep()과 같은 지연 동작은 내부적으로 커널 타이머를 사용하여 프로세스를 특정 시점에 깨우도록 제어됨.

고아 프로세스(Orphan Process)와 입양 메커니즘

  • 정의: 자식 프로세스가 실행 중인 상태에서 부모 프로세스가 먼저 종료된 경우.
  • 입양(Adoption): 커널은 고아가 된 자식의 부모를 시스템 최상위 프로세스인 init(PID 1)으로 변경(Re-parenting)함.
  • 정리 방식:
    • 실행 중인 고아: init에 입양된 후에도 작업을 계속 수행하며, 종료 시점에 initwait()을 호출하여 자원 회수 수행.
    • 좀비 상태의 고아: 부모가 죽기 전 이미 좀비였던 자식은 init에 입양되는 즉시 init에 의해 종료 상태가 수거되어 시스템에서 완전히 제거됨.

wait()waitpid()를 이용한 자원 회수

  • wait(&status): 자식 프로세스가 종료될 때까지 부모 프로세스를 블로킹(Blocking) 상태로 유지하며 종료 상태를 수거함.
  • waitpid(pid_t pid, int *status, int options): 특정 PID의 자식 또는 모든 자식을 대기함. pid-1을 전달하면 임의의 자식 프로세스 종료를 대기함.
  • wait() 계열 함수를 통해 상태를 수거할 경우, 자식 프로세스는 좀비가 되지 않고 시스템에서 완전히 제거됨.

waitpid()WNOHANG 옵션 활용

  • 기능: 종료된 자식이 없더라도 부모가 블로킹되지 않고 즉시 0을 리턴하며 빠져나옴.
  • 장점: 부모 프로세스는 자식의 종료를 기다리는 동안 다른 작업(Non-blocking Polling)을 수행할 수 있음.

활용 예시 (Non-blocking Polling)

while(!waitpid(-1, &status, WNOHANG))
{
    sleep(3);
    puts("sleep 3sec.");
    // 자식의 종료를 기다리는 동안 부모는 다른 작업 수행 가능
}

if(WIFEXITED(status))
    printf("Child send %d \n", WEXITSTATUS(status));

자식 프로세스 종료 상태 확인 매크로

  • WIFEXITED(status): 자식 프로세스가 exit() 또는 return으로 정상 종료되었는지 확인 (정상 종료 시 참).
  • WEXITSTATUS(status): 정상 종료된 자식 프로세스의 종료 코드(리턴값) 확인.
  • WIFSIGNALED(status): 시그널에 의해 비정상 종료되었는지 확인.
  • WTERMSIG(status): 프로세스를 종료시킨 시그널 번호 확인.

시그널(Signal) 메커니즘 개요

  • 정의: 특정 이벤트 발생 시 운영체제가 프로세스에 전달하는 비동기적 알림 메시지.
  • 시그널 등록: 특정 이벤트 발생 시 호출될 함수를 운영체제에 등록하는 과정이며, #include <signal.h> 선언이 필요함.
  • signal() 함수: 시그널과 핸들러 함수를 연결함. (형식: signal(시그널 종류, 핸들러 함수명))
  • 핸들러 함수 프로토타입: void handler(int signo); (리턴 타입 void, 매개변수 int)

SIGCHLD를 이용한 비동기 자식 프로세스 정리

  • 자식 프로세스가 종료되면 커널은 부모에게 SIGCHLD 시그널을 전달함.
  • 이를 활용하여 부모가 다른 작업을 수행하던 중 비동기적으로 자식의 자원을 회수할 수 있음.

SIGCHLD 핸들러 구현 예시

void read_childproc(int sig)
{
    int status;
    pid_t id = waitpid(-1, &status, WNOHANG);
    if(WIFEXITED(status))
    {
        printf("Removed proc id: %d \n", id);
        printf("Child send: %d \n", WEXITSTATUS(status));
    }
}

// main() 함수 내 등록 예시
signal(SIGCHLD, read_childproc);

주요 시그널 유형 및 alarm() 활용

  • 주요 시그널:
    • SIGINT: CTRL+C 입력 시 발생하는 인터럽트 신호.
    • SIGALRM: alarm() 함수 호출 후 설정 시간이 경과하면 발생함.
  • alarm(n) 활용: n초 후 SIGALRM 발생 예약. 핸들러 내 재호출을 통해 주기적 작업 수행 가능. (하드웨어 워치독 메커니즘과 유사)

sleep()과 시그널의 상호작용

  • sleep() 수행 중 시그널 발생 시 핸들러 종료 후 sleep()은 즉시 반환됨.
  • 실행 흐름은 sleep() 호출 바로 다음 줄로 이어짐.
  • 리턴값은 정상 종료 시 0, 중단 시 **남은 시간(초)**을 반환함.

임베디드 시스템 설계 및 모니터링

  • 저전력 설계: main() 구조를 sleep 상태로 유지하고 인터럽트(시그널) 발생 시에만 동작하도록 하여 전원 효율을 최적화함.
  • 좀비 식별 (ps): ps -ef | grep zombie 실행 시 [명칭] <defunct> 형태로 표시됨.
  • 실시간 모니터링 (top): 시스템 내 zombie 프로세스 개수 확인 가능.

[새로운내용]