進程——wait與waitpid、僵屍進程與孤兒進程


僵屍進程:子進程終止了,但是父進程沒有回收子進程的資源PCB。使其成為僵屍進程

孤兒進程:父進程先與子進程結束了,使得子進程失去了父進程,這個時候子進程會被1號進程init進程領養,成為孤兒進程

 

為了防止上面兩種情況,我們應當在父進程結束之前一定要回收子進程的所有資源

所以出現了wait和waitpid

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);


status是一個傳出參數。
waitpid的pid參數選擇:
< -1 回收指定進程組內的任意子進程
= -1 回收任意子進程
= 0  回收和當前調用waitpid一個組的所有子進程
> 0  回收指定ID的子進程

一個進程結束的時候,會關閉所有的文件描述符,釋放所有的內存空間,但是他的PCB仍然存在,保存着子進程的一些狀態信息,如果進程正常退出,保存着正常退出的狀態,如果非正常退出,那么保存着是哪個信號導致的該進程退出,父進程可以通過wait和waitpid查看到這些信息,並且徹底清除,我們知道shell是所有進程的父進程,在shell中可以通過 $查看退出狀態編號,所以可以通過shell查看並清除,如果一個進程退出,父進程並沒有調用wait和waitpid進程清除,那么就產生了僵屍進程,正常情況下,僵屍進程都被父進程清理了

下面寫一個不正常了程序,使得父進程不結束

#include <unistd.h>
#include <stdlib.h>

int main(void)
{
    pid_t pid=fork();

    if(pid<0) {
        perror("fork");
        exit(1);
    }

    if(pid>0) { /* parent */
        while(1);
    }

    /* child */
    return 0;
}

上面中,父進程一直處於while(1)循環,使得父進程不退出,下圖查看ps aux可以發現父進程狀態為R,子進程狀態為Z(僵屍態Zombie)

 

 

 

 

 對於wait或waitpid函數若調用成功則返回清理掉的子進程id若調用出錯則返回-1。父進程調用wait或waitpid時可能會出現一下的情況:

  1. 阻塞(如果它的所有子進程都還在運行)。
  2. 帶子進程的終止信息立即返回(如果一個子進程已終止,正等待父進程讀取其終止信息)。
  3. 出錯立即返回(如果它沒有任何子進程)。

 

 

 上圖看到了,wai成功的返回值

*******************************************************************************************

  對於wait和waitpid兩個函數,有所不同的是:

  1. 如果父進程的所有子進程都還在運行,調用wait將使父進程阻塞,而調用waitpid時如果在options參數中指定WNOHANG可以使父進程不阻塞而立即返回0。
  2. wait等待第一個終止的子進程,而waitpid可以通過pid參數指定等待哪一個子進程。

 

 

所以,調用wait和waitpid不僅可以獲得子進程的終止信息,還可以使父進程阻塞等待子進程終止,起到進程間同步的作用。如果參數status不是空指針,則子進程的終止信息通過這個參數傳出,如果只是為了同步而不關心子進程的終止信息,可以將status參數指定為NULL。 

 

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <sys/types.h>
 5 
 6 int main(void)
 7 {
 8     pid_t pid,pid_c;
 9 
10     int n = 10;
11     pid = fork();
12 
13     if(pid > 0 )
14     {/* in parent */
15         while(1)
16         {
17             printf("I am parent %d\n",getpid());
18             //wait是一個阻塞函數,等待回收子進程資源,如果沒有子進程,wait返回-1
19             pid_c = wait(NULL);
20             printf("wait for child %d\n",pid_c);
21             sleep(1);
22         }
23     }
24     else if(pid == 0)
25     {/* in child */
26         printf("I am child %d\n",getpid());
27         sleep(10);
28     }
29 
30     return 0;
31 }
32 
33 
34 運行結果:
35 I am parent 4797
36 I am child 4798
37 wait for child 4798
38 I am parent 4797
39 wait for child -1
40 I am parent 4797
41 wait for child -1
42 I am parent 4797

 

孤兒進程

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
    pid_t pid;
    int n=10;
    pid = fork();
    if(pid > 0)
    {//創建完之后父進程就退出了
        printf("I am parent\n");
        exit(0);
    }
    else if(pid == 0)
    {//此時父進程退出,子進程被init程序接管,該進程的父進程號變成1
        while(n--)
        {
            printf("I am %d, my parent is %d\n",getpid(),getppid());
            sleep(1);
        }
    }
    else
    {
        perror("fork");
        exit(-1);
    }
    return 0;
}


運行結果:
I am 4813, my parent is 1
I am 4813, my parent is 1
I am 4813, my parent is 1
I am 4813, my parent is 1
I am 4813, my parent is 1
I am 4813, my parent is 1

waitpad

 1 #include <sys/types.h>
 2 #include <sys/wait.h>
 3 #include <unistd.h>
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 
 7 int main(void)
 8 {
 9     pid_t pid;
10     pid = fork();
11     if (pid < 0)
12     {
13         perror("fork failed");
14         exit(1);
15     }
16 
17     if (pid == 0)
18     {//in child
19         int i;
20         for (i = 3; i > 0; i--) {
21             printf("This is the child %d\n",getpid());
22             sleep(1);
23         }
24         exit(3);//返回3,運行時可以看到
25         //子進程睡眠3秒之后就退出了
26     }
27 
28     else
29     {//in parent
30         int stat_val;
31         waitpid(pid, &stat_val, 0);//以阻塞方式等待回收子進程,第三個參數0,表示阻塞方式
32         if (WIFEXITED(stat_val))//正常退出
33             printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
34         else if (WIFSIGNALED(stat_val))//查看被什么信號關閉
35     printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
36     }
37     return 0;
38 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM