linux 創建進程

1:fork()

在linux中可以使用fork()來創建一個進程,來看下函數的定義以及返回值

函數原型     pid_t fork(void)
函數返回值:
    0: 子進程
    -1: 出錯
    >0(爲子進程ID): 父進程  

頭文件:include<sys/types.h>
       inculde<unistd.h>

fork()函數用於從已存在的進程中創建一個新的進程。新進程爲子進程,而原進程稱爲父進程。使用fork()函數得到的子進程時父進程的一個複製品,它從父進程處繼承了整個進程的地址空間,包括進程上下文,代碼段,進程堆棧,內存信息,文件描述符,信號控制設定,進程優先級,進程組號,當前工作目錄,根目錄,資源限制和控制終端等,而子進程所獨有的只有它的進程號,資源使用和計時器等子進程幾乎是父進程的完全複製,所以父子進程會同時運行一個程序。

下面來看一個例子:

#inculde <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    pid_t result;

    /*create new process */
    result = fork();
    if (-1 == result)
    {
        printf("Fork error\n");
    } else if (result == 0) /* children process */
    {
        printf("Child process id is %d\n", getpid());
    } else
    {
        printf("Father process id is %d \n", getpid());
     }

     return result;
 運行結果:
 Father process id is 6798
 Child  process is is 6799


fork出錯可能有兩種原因:
1:當前進程數目達到了系統規定的上限,這是error的值被設置爲EAGAIN
2:系統內存不足,這時error的值被設置爲ENOMEM.

可以看到fork()函數看起來執行一次卻有兩個返回值。這時因爲fork()執行時,父進程會複製出一個子進程,而父子進程的代碼從fork()函數的返回開始分別在各自的地址空間同時運行,從而是兩個進程分別獲得其所屬fork的返回值,其中在父進程中返回的是子進程的進程號,而在進程中返回0.因此,可以分別通過返回值來判定該進程時父進程還是子進程。
2:寫時拷貝

在傳統的fork()時,子進程會直接把所有的父進程資源完全複製給新創建的進程,因此執行速度比較慢,而且實現過於簡單,因爲它拷貝的數據並不共享。更糟糕的情況是,如果新進程打算立即執行一個新的映像,那麼所有的copy都將前功盡棄。linux的fork使用寫時拷貝(copy-on-write)頁實現。而寫時拷貝是一種可以推遲甚至免除拷貝數據的技術。內核此時並不是複製整個進程地址空間,而是讓父進程和子進程共享同一個拷貝。
只有在需要寫入的時候,數據纔會被複制,從而使各個進程擁有各自的拷貝。也就是說,資源的複製只有在需要寫入的時候才進行,在此之前,只是以只讀方式共享。這種技術使地址空間上的頁的拷貝被推遲到實際發生寫入的時候才進行。在頁根本不會寫入的情況下,它們就無需複製。
這樣fork()的實際開銷就是複製父進程的頁表已經給子進程創建唯一的進程描述符。在一般情況下,子進程創建後都馬上運行一個可執行的文件,這種優化可以避免拷貝大量根本就不會被使用的數據。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章