zombie

於程式中查看到signal(SIGCHLD,SIG_IGN),了解一下用意


更新記錄

item note
20160908 第一版

目錄


彊屍程序(zombie)

僵屍 (zombie) 程序是什麼

造成僵屍程序的成因是因為該程序應該已經執行完畢,或者是因故應該要終止了, 但是該程序的父程序卻無法完整的將該程序結束掉,而造成那個程序一直存在記憶體當中

ps

  • ps

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    xx :[~]# ps
    PID USER VSZ STAT COMMAND
    1 root 2164 S init
    2 root 0 SW [kthreadd]
    3 root 0 SW [ksoftirqd/0]
    xx
    1315 root 1604 S ./a.out
    1316 root 0 Z [a.out]
    1317 root 0 Z [a.out]
    1318 root 0 Z [a.out]
    1319 root 0 Z [a.out]
    1320 root 0 Z [a.out]
  • VSZ : 該 process 使用掉的虛擬記憶體量 (Kbytes)

  • STAT : 該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z)
    • R (Running)
    • S (Sleep):該程式目前正在睡眠狀態(idle),但可以被喚醒(signal)
    • T :停止狀態(stop),可能是在工作控制(背景暫停)或除錯 (traced) 狀態
    • Z (Zombie):僵屍狀態,程序已經終止但卻無法被移除至記憶體外

example (未加入SIGCHLD訊息處理)

  • 未加入SIGCHLD訊息處理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>
    #include <unistd.h>

    int main(){
    int i;
    pid_t pid;

    for( i=0; i<5; i++) {
    pid = fork();
    if ( pid == 0 )
    break;
    }
    if( pid > 0 ){
    printf("press enter to exit ..");
    getchar();
    }
    return 0;
    }
  • 結果如下
    當子程序結束,父程序仍在
    而父程序fork()之前未設置SIGCHILD信號處理或waitpid等待子程序結束
    此時會產生 僵屍程序(zombie), 若父程序一直存在不會結束,就會看到一堆zombie

    1
    2
    3
    4
    5
    6
    1315 root      1604 S    ./a.out
    1316 root 0 Z [a.out]
    1317 root 0 Z [a.out]
    1318 root 0 Z [a.out]
    1319 root 0 Z [a.out]
    1320 root 0 Z [a.out]

example (加入SIGCHLD訊息處理)

  • 加入SIGCHLD訊息處理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/signal.h>

    int main(){
    int i;
    pid_t pid;
    signal(SIGCHLD, SIG_IGN);
    for( i=0; i<5; i++) {
    pid = fork();
    if ( pid == 0 )
    break;
    }
    if( pid > 0 ){
    printf("press enter to exit ..");
    getchar();
    }
    return 0;
    }
  • 測試

    1
    2
    1454 root      1604 S    ./a.out
    1460 root 2168 R ps

fork

  • The purpose of fork() is to create a new process, which becomes the child process of the caller
  • If fork() returns a negative value, the creation of a child process was unsuccessful.
  • fork() returns a zero to the newly created child process.
  • fork() returns a positive value, the process ID of the child process, to the parent.
  • The fork() System Call

fork example

  • ex1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>

    void main(void)
    {
    pid_t pid;
    int i;
    char buf[100];

    fork();
    pid = getpid();
    for(i =1; i <= 200; i++){
    sprintf(buf, "This line is from pid %d, value = %d \n", pid, i);
    write(1,buf,strlen(buf));
    }
    }
  • 測試

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    xx :[~]# ./a.out 
    This line is from pid 1498, value = 1
    This line is from pid 1498, value = 2
    This line is from pid 1498, value = 3
    This line is from pid 1498, value = 4
    This line is from pid 1498, value = 5
    This line is from pid 1498, value = 6
    This line is from pid 1498, value = 7
    This line is from pid 1498, value = 8
    This line is from pid 1498, value = 9
    This line is from pid 1499, value = 1
    This line is from pid 1498, value = 10
    This line is from pid 1499, value = 2

fork之後會產生1個子程序,跟父程序同時進行,因此會看到有兩個pid,獨立算數
fork出來的子程序是由原本的父程序複製全部的變數(kernel需要的系統參數),因此是跟父程序獨立分開的process

fork ex2

  • fork ex2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>

    void ChildProcess(){
    pid_t pid;
    pid = getpid();
    printf("child pid:%d\n",pid);
    getchar();
    }
    void ParentProcess(){
    pid_t pid;
    pid = getpid();
    printf("parent pid:%d\n",pid);
    getchar();
    }
    void main(void)
    {
    pid_t pid;
    int i;
    char buf[100];

    pid = fork();
    if ( pid == 0 )
    ChildProcess();
    else
    ParentProcess();

    }
  • 測試

    1
    2
    1559 root      1604 S    ./a.out
    1560 root 1604 S ./a.out
  • fork回傳0則為child process


參考