轉:fork的解釋

原文來自於:http://baike.baidu.com/view/1952900.htm?fr=aladdin函數

fork編輯

叉子\分岔\岔口\復刻,西方人吃飯用的東西,常常用做刀和叉。
計算機 程序設計中的分叉函數。返回值: 若成功調用一次則返回兩個值,子進程返回0, 父進程返回子進程標記;不然,出錯返回-1。
fork函數將運行着的程序分紅2個(幾乎)徹底同樣的進程,每一個進程都啓動一個從代碼的同一位置開始執行的線程。這兩個進程中的線程繼續執行,就像是兩個用戶同時啓動了改應用程序的兩個副本。
 

1分叉函數編輯

頭文件

1
2
#include<unistd.h>/*#包含<unistd.h>*/
#include<sys/types.h>/*#包含<sys/types.h>*/

函數原型

pid_t forkvoid);
(pid_t 是一個 宏定義,其實質是int 被定義在# include< sys/types.h>中)
返回值: 若成功調用一次則返回兩個值,子進程返回0, 父進程返回子進程ID;不然,出錯返回-1

函數說明

一個現有進程能夠調用fork函數建立一個新進程。由fork建立的新進程被稱爲子進程(child process)。fork函數被調用一次但返回兩次。兩次返回的惟一區別是子進程中返回0值而 父進程中返回子進程ID。
子進程是 父進程的副本,它將得到父進程數據空間、堆、棧等資源的副本。注意,子進程持有的是上述 存儲空間的「副本」,這意味着父子進程間不共享這些存儲空間。
UNIX將複製 父進程地址空間內容給子進程,所以,子進程有了獨立的地址空間。在不一樣的UNIX (Like)系統下,咱們沒法肯定fork以後是子進程先運行仍是父進程先運行,這依賴於系統的實現。因此在移植代碼的時候咱們不該該對此做出任何的假設。
爲何fork會返回兩次?
因爲在複製時複製了 父進程堆棧段,因此兩個進程都停留在fork函數中,等待返回。所以fork函數會返回兩次,一次是在 父進程中返回,另外一次是在子進程中返回,這兩次的返回值是不同的。過程以下圖。
 
  1. fork調用的一個奇妙之處就是它僅僅被調用一次,卻可以返回兩次,它可能有三種不一樣的返回值:
      在父進程中,fork返回新建立子進程的進程ID;
  2. 在子進程中,fork返回0;
  3. 若是出現錯誤,fork返回一個負值。
在fork函數執行完畢後,若是建立新進程成功,則出現兩個進程,一個是子進程,一個是父進程。在子進程中,fork函數返回0,在父進程中,fork返回新建立子進程的進程ID。咱們能夠經過fork返回的值來判斷當前進程是子進程仍是父進程。
引用一位網友的話來解釋fork函數返回的值爲何在父子進程中不一樣。「其實就至關於鏈表,進程造成了鏈表,父進程的fork函數返回的值指向子進程的進程id, 由於子進程沒有子進程,因此其fork函數返回的值爲0.
調用fork以後,數據、 堆棧有兩份,代碼仍然爲一份可是這個 代碼段成爲兩個進程的共享代碼段都從fork函數中返回,箭頭表示各自的執行處。當父子進程有一個想要修改數據或者堆棧時,兩個進程真正分裂。
示例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<sys/types.h>//對於此程序而言此頭文件types.h用不到
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
 
intmain(intargc, char *argv[]) /*整數類型主函數*/
{
pid_tpid=fork(); /*傳遞參數*/
if (pid<0) /*若是(進程標記<0)*/
{
fprintf (stderr, "錯誤!" );
}
elseif(pid==0) /*不然若是(進程標記==0)*/
{
printf ( "百度百科:這是子進程!" );
exit (0);
}
else /*不然*/ {
printf ( "百度百科:這是父進程!子進程的進程標記爲=%d" ,pid);
}
//可能須要時候wait或waitpid函數等待子進程的結束並獲取結束狀態
exit (0);
}
注意!樣例代碼僅供參考,樣例代碼存在着父進程在子進程結束前結束的可能性。必要的時候可使用wait或 waitpid函數讓父進程等待子進程的結束並獲取子進程的返回狀態。
fork()在Linux系統中的返回值是沒有NULL的.
Error Codes
出錯返回 錯誤信息以下:
EAGAIN
達到進程數上限.
ENOMEM
沒有足夠空間給一個新進程分配.
fork函數的特色歸納起來就是「調用一次,返回兩次」,在 父進程中調用一次,在父進程和子進程中各返回一次。
fork的另外一個特性是全部由 父進程打開的描述符都被複制到子進程中。父、子進程中相同編號的 文件描述符內核中指向同一個file 結構體,也就是說,file結構體的 引用計數要增長。
[1]  

2中文翻譯編輯

叉子\分岔\岔口\復刻,西方人吃飯用的東西,常常用做刀和叉。
 
參考資料
  • 1.  Robert Love .Linux Kernel Development(Third Edition) :機械工業出版社 ,2011.6 .spa

相關文章
相關標籤/搜索