C

fork 系統呼叫是如何工作的

  • March 9, 2017

我有一個關於 fork 系統呼叫的非常具體的問題。我有這段程式碼:

int main (void) 
{
   for (int i = 0; i < 10; i++) {
       pid_t pid = fork ();

       if ( !pid ) {
           printf("CHILD | PID: %d, PPID: %d\n", getpid(), getppid());
           _exit(i + 1);
       }

   }

   for (int i = 0; i < 10; i++) {
       int status;
       waitpid(-1, &status, 0);

       if (WIFEXITED(status)) {
           printf("IM %d AND CHILD WITH EXIT CODE %d TERMINATED\n",
                   getpid(), WEXITSTATUS(status));

       } 
       else {
           printf("ERROR: CHILD NOT EXITED\n");
       }
   }

   return 0;
}

產生這個輸出:

CHILD | PID: 3565, PPID: 3564
CHILD | PID: 3566, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 1 TERMINATED
IM 3564 AND CHILD WITH EXIT CODE 2 TERMINATED
CHILD | PID: 3573, PPID: 3564
CHILD | PID: 3567, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 9 TERMINATED
IM 3564 AND CHILD WITH EXIT CODE 3 TERMINATED
CHILD | PID: 3568, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 4 TERMINATED
CHILD | PID: 3569, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 5 TERMINATED
CHILD | PID: 3570, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 6 TERMINATED
CHILD | PID: 3571, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 7 TERMINATED
CHILD | PID: 3572, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 8 TERMINATED
CHILD | PID: 3574, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 10 TERMINATED

這讓我想知道 fork 到底是如何工作的,以及新程序真正執行了哪些程式碼。看上面的輸出結果,看不懂:

  1. 在第一個完成所有迭代之前,第二個循環如何列印?我還注意到第二個 for總是由父程序執行,這讓我想知道 while on first for cycle(這意味著父程序呼叫)第二個 for cycle是否被執行(?)if pid != 0
  2. 為什麼 CHILD 程序不按 PID 排序列印?

那麼,最重要的是,fork 究竟是如何工作的,誰執行了什麼?

當你fork時,核心創建一個新程序,它是分叉程序的副本,兩個程序在之後繼續執行fork(返回程式碼顯示是否發生錯誤,以及正在執行的程式碼是父程序還是子程序)。這個“繼續執行”的部分不一定會立即發生:核心只是將新程序添加到執行隊列中,它最終會被調度並執行,但不一定立即執行。

這解釋了您所詢問的兩種行為:

  • 由於不一定會立即安排新程序,因此父程序可能會在任何子程序有機會執行之前繼續執行;
  • 創建順序在執行隊列中沒有太大(如果有的話)影響,因此不能保證子程序將按照它們創建的順序執行。

引用自:https://unix.stackexchange.com/questions/350301