Linux 進程創建二(execve和wait)


三:execve系統調用
int execve(const char *filename, char *const argv[],char *const envp[]);
fork創建了一個新的進程,產生一個新的PID
execve用被執行的程序完全替換了調用進程的映像。
execve啟動一個新程序,替換原有進程,所以被執行進程的PID不會改變。
execve函數接受三個參數
--path    要執行的文件完整路徑
--argv    傳遞給程序完成參數列表,包括argv[0],它一般是執行程序的名字,最后一個參數一般是NULL
--envp    是指向執行execed程序的環境指針,一般設為NULL

 

//execve函數的定義
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

int main(int arg, char * args[])
{
    /*
      第一個參數是程序的名字,第二個參數是被調用程序的參數,最后一個參數必須是NULL
      這個跟main函數的參數args數組很相似
     */
    char * argv[]={"/bin/ls","-l",NULL};
    execve("/bin/ls",argv,NULL);
    /*
     execve函數是替換原來的程序代碼,但是進程PID不會變,文件描述符不會變,只是程序代碼被替換了
     所以execve函數后面的語句都不會被執行
     */
    printf("program is end!\n");
    return 0;
}

 

wait和waitpid函數可以收集子進程的退出狀態
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
stauts保存子進程的退出狀態(本質上就是子進程的返回值,但是我們不能直接查看這個返回值,必須用宏定義轉化一下)
在waitpid函數中,參數pid是等待進程的PID,他能夠接受一下四種值
    "<-1"    等待任何PGID等於PID的絕對值子進程
    "-1"    等待任何子進程(這個進程創建的子進程)
    "0"    等待任何PGID等於調用進程的子進程
    ">0"    等待PID等於pid的子進程    

 

//wait函數的定義
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int arg, char * args[])
{
    pid_t child=0;
    int status=0;
    child=fork();
    if(child==-1)
    {
        printf("system is game over!\n");
        return -1;
    }
    if(child==0)
    {
        //in child process
        printf("child is begining!\n");
        sleep(3);
        printf("child is end , now is your turn!\n");
    }else{
        //in parent process
        printf("parent is begining , i am wait my son!\n");
        wait(&status);
        printf("child status=%d\n",WEXITSTATUS(status));
        printf("my son is end , now i am go !\n");
    }
    printf("all is end!\n");
    return 10;
}

 

 

 

用fork或者execve函數創建一個新進程,為了收集新進程的退出狀態並且防止出現僵死進程(zombie process),父進程應該調用wait或者waitpid函數等待進程終止。

 

僵死進程
一個僵死進程是在父進程退出之前就終止的子進程(子進程在父進程之前終止,此時因為父進程還沒有退出,所以系統會保留子進程的pid,退出 狀態,返回給父進程有wait函數,如果父進程沒有wait函數,系統就會一直保持子進程的PID等信息,直到父進程退出)
之所以被稱為僵死進程是因為他雖然死掉了,但依然在進程表中存在。
子進程退出后分配給他的內存和其他資源都被釋放,但是子進程還在內核進程表保留一條,內核在父進程回收子進程的退出狀態前一直保留它。
有一個兩個僵死進程不算什么問題,但一旦一個程序頻繁執行fork或者execv卻又不能手機退出狀態,那么最終將會填滿進程表(內核進程表是有上限的),這會影響性能,可能導致系統重啟

 

 

孤兒進程
孤兒進程是一個父進程在調用wait或者waitpid之前就已經退出了(即父進程在子進程之前退出)。此時init進程成為子進程的父進程。
init進程成為子進程的父進程,收集子進程的退出狀態,從而避免出現僵死進程。
注意:任何一個進程都必須有父進程,init的父進程是0號進程,父進程與子進程是相對獨立的(子進程會拷貝進程控制器和代碼區,寫時拷貝數據區),父進程退出,子進程不一定會退出

 


免責聲明!

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



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