본문 바로가기
프로...Linux

[Process] Zombie

by 크크다스 2019. 5. 28.
반응형

[Process] Zombie

좀비 프로세스들이 계속 생긴다, 어찌해야 할까?

1. 부모를 찾아라

2, 부모의 SIGCHLD 를 설정해주어라. (쉽게 SIG_IGN)

1. 부모를 찾아라

아래 표시위치가 부모 프로세스임.

cat /proc/[PID]/stat

# cat /proc/25955/stat

25955 (sh) Z 25828 23995 5816 0 -1 4227084 131 164 0 0 1 1 0 0 20 0 1 0 345286 0 0 2147483647 0 0 0 0 0 0 0 4 2 0 0 0 18 0 0 0 0 0 0 0 0 0



2, 부모의 SIGCHLD 를 설정해주어라. (쉽게 SIG_IGN)

프로세스 기동 부분에 SIG Handler를 등록한다.

[비추천]

signal(SIG_CHLD, SIG_IGN);

[추천]

    struct sigaction sa;

    sa.sa_handler = SIG_IGN;

    sa.sa_flags = 0;

    sigaction(SIGCHLD, &sa, NULL);


펌> 사이트가 검색이 안되어 저장 차원에서 퍼옴

출처> https://webcache.googleusercontent.com/search?q=cache:7jwxwyFeA9AJ:https://reachlabkr.wordpress.com/2014/06/22/c-zombie-process-%25EC%25B2%2598%25EB%25A6%25AC/+&cd=1&hl=ko&ct=clnk&gl=kr

[C] Zombie process 처리

좀비 프로세스란 fork() 하여 생성한 자식 프로세스는 죽었지만 부모가 그 자원을 회수 하지 않아서 생기는 프로세스입니다. 
이 프로세스들은 ps -ef 명령으로 확인하면 라고 표시됩니다.

좀비 프로세스는 보통 자신이 사용하던 리소스는 모드 해제된 상태이지만 커널에 의해서 프로세스 테이블에서는 관리되고 있는 상태가 됩니다. 
좀비 프로세스가 많이 생긴다면 커널에 좋지 않은 영향을 끼치게 됩니다.

좀비 프로세스는 보통 자신의 부모 프로세스가 wait(), waitpid() 함수를 호출하거나 부모가 죽게 되면 없어지게 됩니다.

좀비 프로세스를 처리하는 방법

동기식 처리방법

waitpid() 함수를 호출하여 자식 프로세스가 끝날때까지 부모 프로세스는 block 상태로 대기합니다.

예>

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    int pid;
    int status;
    int spid;
    pid = fork();

    if (pid == 0) {
        sleep(5);
        printf("I will be back %d\n", getpid());
        return 1;
    } else if(pid > 0) {
        printf("Im parent %d\n", getpid());
        printf("Press any key and wait\n");
        getchar();
        // 자식프로세스를 wait 합니다.
        // 자식프로세스의 종료상태는 status 를 통해 받아옵니다.
        spid = waitpid(pid, &status, 0);
        printf("자식프로세스 wait 성공 \n");
        printf("Exit Value  : %d\n", WEXITSTATUS(status));
        printf("Exit Stat   : %d\n", WIFEXITED(status));
    } else {
        perror("fork error :");
    }
}

비 동기식 처리방법

SIGCHLD 에 대한 signal 핸들러를 등록하여 놓고 부모 프로세스는 fork() 후 자신이 하던일을 계속하고, 자식 프로세스가 종료되어 SIGCHLD signal이 발생하면 signal 핸들러 안에서 waitpid() 함수를 이용하여 자식 프로세스의 자원을 해제 합니다.

signal 핸들러 등록시 sa_flag에 SA_NODEFER 과 SA_NOCLDWAIT를 지정해 줍니다. 
1. SA_NODEFER: SIGCHLD 핸들러 수행시 SIGCHLD 시그널이 발생하면 누적 횟수만큼 SIGCHLD 핸들러를 호출해주어 signal의 누락을 막아줍니다. 
2. SA_NOCLDWAIT: SIGCHLD 핸들러안의 waitpid()가 호출 되기전에 자식프로세스가 좀비 프로세스가 되는 것을 방지합니다.

예>

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

void handler(int sig) {   // SIGCHLD 처리
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

int main(int argc, char** argv) {
    int i;
    pid_t child;
    struct sigaction sa;
    sa.sa_handler = handler;
    sa.sa_flags = SA_NODEFER | SA_NOCLDWAIT;
    sigemptyset(&sa.sa_mask);
    sa.sa_restorer = NULL;
    sigaction(SIGCHLD, &sa, NULL);

    for(i = 0; i < 10; ++i) {
        child = fork();
        if(child == 0) {
            child = getpid();
            printf("child %d exiting\n", child);
            exit(0); // child process는 바로 종료
        }
    }

    while(1) pause(); // waiting for signal
    return 0;
}

무시하는 방법

SIGCHLD 에 대한 signal 행동 방식을 SIG_IGN 시그널 무시로 해놓아 자식 프로세스가 종료 되더라도 좀비 프로세스가 생성되지 않게 합니다.

이 방식의 경우는 자식 프로세스의 상태를 가져올수 없다는 단점이 있긴 하지만, 신경 쓸거 없이 깔끔합니다.

예>

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    int i;
    pid_t child;
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = 0;
    sigaction(SIGCHLD, &sa, NULL);

    for(i = 0; i < 10; ++i) {
        child = fork();
        if(child == 0) {
            child = getpid();
            printf("child %d exiting\n", child);
            exit(0); // child process는 바로 종료
        }
    }

    while(1) pause(); // waiting for signal
    return 0; 

}


반응형

'프로...Linux' 카테고리의 다른 글

[Util-Script] mytop  (0) 2019.10.18
[Threads] 속성 및 내용 정리  (0) 2019.09.19
[Perl] 인코딩 변환  (0) 2019.04.03
[SHELL] bash/sh 실수 계산 작업  (0) 2019.04.02
[Locale] 언어 설정(ko_KR : euckr / utf8)  (1) 2019.04.01