簡體   English   中英

Fork和Execlp

[英]Fork and Execlp

我嘗試使用fork和execlp的程序,其中父地址空間被“ls”命令替換。

#include<stdio.h>
main()
{
    int pid,j=10,fd;
    pid=fork();
    if(pid==0)
    {
        printf("\nI am the child\n");
        execlp("/bin/ls","ls",NULL);
        printf("\nStill I am the child\n");

    }
    else if (pid > 0)
    {
        printf("\n I am the parent\n");
        wait();
    } 
}

當我執行程序時,最后一行的孩子

printf("\nStill I am the child\n");

沒有打印。 為什么?

exec系列函數在成功時不返回。

http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html

exec系列函數應使用新的過程映像替換當前過程映像。 新圖像應由稱為新過程映像文件的常規可執行文件構成。 成功的exec不會返回,因為調用過程映像被新的過程映像覆蓋。

如果其中一個exec函數返回到調用進程映像,則發生錯誤; 返回值應為-1,並設置errno以指示錯誤。

exec函數不僅會執行您的命令。 它們實際上會用您選擇的可執行文件替換進程的執行上下文(在您的case /bin/ls )。

換句話說,由於ls函數通過終止其進程(“退出”或返回主函數或其他任何東西)而結束,因此您的子進程將在ls執行結束時被終止。

您實際上可以使用此printf調用來打印一些錯誤,例如:

 if(pid==0)
    {
        printf("\nI am the child\n");
        execlp("/bin/ls","ls",NULL);
        printf("\nError: Could not execute function %s\n", "/bin/ls");
        _exit(0); //make sure you kill your process, it won't disappear by itself. 
    }

原因很簡單:exec()函數僅在發生錯誤時才返回。 對於exec()函數的相同參考手冊頁。

調用exec()函數時到底發生了什么:

execl()不會創建新進程 - 它會修改VADS和相關內容 - 此外,還會修改執行上下文。

  • 不再使用舊的執行上下文 - 創建新的執行上下文。
    • 為新加載的應用程序創建一個新的,全新的上下文,並將控制傳遞給調度程序 - 調度程序使用新的可用執行上下文恢復相同的子進程 - 使用此操作,執行跳轉到新應用程序的入口點, user-space - 新應用程序在同一子進程中開始執行。
      • 系統堆棧被新的hw上下文覆蓋,用於在用戶空間中恢復新程序的main()。
    • 子進程中的舊應用程序的執行上下文和代碼/數據/堆/堆棧被完全銷毀 - 不再可用。
    • 只有當execve()或execl()無法在當前進程中加載​​新應用程序時,execve()或execl()才會返回當前進程的相同應用程序/代碼 - 這意味着,execv()/唯一的時間execvl()或調用系列將在完成execv()/ execl()/系列調用時出錯。

注意:您必須驗證exec()系列調用API的返回值以查找錯誤/錯誤代碼 - 根據錯誤/錯誤代碼,您可以終止當前進程或采取其他一些操作。

函數execlp()沒有按照execlp的文檔執行,因此你的printf()語句“我仍然是孩子”不會被執行...... !!

  1. 您將進程ID作為int類型,但實際上,要存儲進程ID,您應該使用pid_t
  2. 當您使用exec系列函數時,被調用進程的整個地址空間將替換調用進程。 所以,現在最后一個printf語句不在新進程中,實際上甚至進程的進程id也沒有改變

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM