fork函數

fork

返回值: 若成功調用一次則返回兩個值,子進程返回0,父進程返回子進程ID;否則,出錯返回-1

1fork()函數 UNIX

頭文件:

#include<unistd.h>
#include<sys/types.h>

函數原型:

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

函數說明:

一個現有進程可以調用fork函數創建一個新進程。由fork創建的新進程被稱爲子進程(child process)。fork函數被調用一次但返回兩次。兩次返回的唯一區別是子進程中返回0值而父進程中返回子進程ID。
子進程是父進程的副本,它將獲得父進程數據空間、堆、棧等資源的副本。注意,子進程持有的是上述存儲空間的“副本”,這意味着父子進程間不共享這些存儲空間。
UNIX將複製父進程地址空間內容給子進程,因此,子進程有了獨立的地址空間。在不同的UNIX (Like)系統下,我們無法確定fork之後是子進程先運行還是父進程先運行,這依賴於系統的實現。所以在移植代碼的時候我們不應該對此作出任何的假設。

爲什麼fork會返回兩次?

由於在複製時複製了父進程堆棧段,所以兩個進程都停留在fork函數中,等待返回。因此fork函數會返回兩次,一次是在父進程中返回,另一次是在子進程中返回,這兩次的返回值是不一樣的。過程如下圖
調用fork之後,數據、堆棧有兩份,代碼仍然爲一份但是這個代碼段成爲兩個進程的共享代碼段都從fork函數中返回,箭頭表示各自的執行處。當父子進程有一個想要修改數據或者堆棧時,兩個進程真正分裂。
示例代碼:
#include<sys/types.h> //對於此程序而言此頭文件用不到
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char ** argv )
{
pid_t pid = fork();
if (pid < 0)
{
fprintf(stderr, "error!");
}
else if( 0 == pid )
{
printf("This is the child process!");
_exit(0);
}
else
{
printf("This is the parent process! child process id = %d", pid);
}
//可能需要時候wait或waitpid函數等待子進程的結束並獲取結束狀態
exit(0);
}
注意!樣例代碼僅供參考,樣例代碼存在着父進程在子進程結束前結束的可能性。必要的時候可以使用wait或 waitpid函數讓父進程等待子進程的結束並獲取子進程的返回狀態。
fork()在Linux系統中的返回值是沒有NULL的.
Error Codes
出錯返回錯誤信息如下:
EAGAIN
達到進程數上限.
ENOMEM
沒有足夠空間給一個新進程分配.
fork函數的特點概括起來就是“調用一次,返回兩次”,在父進程中調用一次,在父進程和子進程中各返回一次。
fork的另一個特性是所有由父進程打開的描述符都被複制到子進程中。父、子進程中相同編號的文件描述符內核中指向同一個file結構體,也就是說,file結構體的引用計數要增加。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章