1. 程式人生 > >Linux建立程序的fork()函式

Linux建立程序的fork()函式

         在Linux中,fork函式的功能就是在一個程序中建立一個新的程序,當前呼叫fork函式的程序就是產生的新程序的父程序,新程序在以下也稱為子程序。在新程序生成之後就會在系統中開始執行。

  函式原型:其中pid_t 是一個long。

pid_t fork(void); 

        在父程序中,返回值是子程序的程序ID,而在子程序中,返回值則是0,所以可以通過判斷fork函式的返回值來判斷當前執行的是父程序還是子程序。

        建立之後的子程序與父程序執行相同的程式段,但是擁有不同的堆疊段以及資料段,但是子程序中堆疊段和資料段都是父程序的完全複製,直到呼叫exec()函式簇讓子程序去執行的新的程式碼,子程序就完全擁有了屬於自己的程式碼段、堆疊段和資料段。

        在這個過程中,期初的Linux系統,確實是將父程序的所有記憶體進行復制產生新的程序映像,但太浪費記憶體了,所以現在並不會直接複製父程序的所有記憶體,而是子程序與父程序共享程式碼段,子程序的一系列程序級列表都指向父程序的頁表,在exec()函式呼叫之後,再對子程序的頁表進行相應的調整,這個操作就用到了寫時複製技術(copy-on-write),也就是從這一刻起,子程序開始獨立地執行新的程式碼段。

示例程式碼:

  pid_t childPid;
 switch(childPid = fork()) {
    case -1:
    //error
    break;
 
   case 0:
    //child process
    break;
    
    default:
    //father process comes here after fork()
}

       當程序建立失敗時,fork()的返回值存放在errno中,當其為EAGAIN是,原因是程序的數目超過了當前允許建立的程序數量的最大值;當其為ENOMEM,表示記憶體不足,無法配置核心所需的資料結構空間。

       在Linux中,與fork()功能類似還有一個函式vfork(),這個函式也是建立一個程序,但是與fork()有一些不同,vfork()的設計理念是在建立新程序之後,阻塞父程序,用子程序直接執行新的程式碼,並且使用父程序的記憶體,直到子程序執行完畢返回,父程序才會繼續執行。在早期的Linux中vfork()比fork()更高效,因為vfork()不會只會複製父程序的部分內容,但是在現在的Linux系統中,由於寫時複製技術,fork()的效率大大提高,甚至和fork()不相上下,所以儘量避免使用vfork()函式。而且由於vfork()建立的程序與父程序共享記憶體,極有可能出現各種未知的錯誤,這也是避免使用vfork()的重要原因。