1. fork系統調用頭檔案:<unistd.h>;
2. fork系統調用的原型:pid_t fork();
3. fork系統調用的傳回值:pid_t是程序描述符類型,本質就是一個int。如果fork函數執行失敗,傳回一個負數(<0);如果fork調用執行成功,傳回兩個值:0和所建立子程序的ID。
4. fork系統調用的功能:以目前程序作為父程序建立出一個新的子程序,并且将父程序的所有資源拷貝給子程序,這樣子程序作為父程序的一個副本存在。父子程序幾乎時完全相同的,但也有不同的如父子程序ID不同。
5. 注意:當fork系統調用成功時,它會傳回兩個值:一個是0,另一個是所建立的新的子程序的ID(>0)。當fork成功調用後此時有兩個資料相同的父子程序,我們可以通過fork的傳回值來判斷接下來程式是在執行父程序還是子程序。
pid_t pid = fork();
if(pid == 0)
{
//在子程序中
}
else if(pid > 0)
{
//在父程序中
}
else
{
//fork調用失敗
}
6. fork調用與檔案描述符的關系
前面我們知道當我們使用fork系統調用以目前程序作為父程序建立出了一個子程序,父程序将自己的在fork系統調用之前的所有資料和代碼都複制一份給子程序,此時子程序相當于父程序的一個拷貝。對于在fork調用之前打開的檔案也一樣,也會做一個拷貝将檔案描述符複制給子程序,這樣父子程序可以同時對一個檔案進行操作。但是這種操作是共享式的,父子程序共享這個檔案描述符所索引的檔案。何謂父子程序共享這個檔案呢?舉個簡單例子說明下
如果一個已經打開的txt檔案,裡邊的内容是一個字元串“abcdefg”。在父程序中讀取前兩個字元“ab”,此時檔案指針指向c。如果在子程序中再次讀取兩個字元,那麼它讀取就是“cd”,并且讀完後檔案指針指向e。這就是父子程序以共享的方式來操作檔案。下面我們通過代碼說明這個關系:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<iostream>
#include<pthread.h>
#include<fcntl.h>//為了使用O_RD_ONLY
int gb = 10;
using namespace std;
int main()
{
int fd = open("fork.txt", O_RDONLY);
if(fd < 0)//檔案描述符是一個非負整數:0是stdin的檔案描述符,1是stdout的檔案描述符,2是stderr的檔案描述符
{
cout<<"error in open the file!"<<endl;
exit(1);
}
cout<<"檔案描述符為:"<<fd<<endl;
char *c = new char[3];
int a = 5;
cout<<"main函數中的程序ID:"<<getpid()<<endl;
pid_t pid = fork();//fork系統調用的作用是:使用目前程序作為副本建立出一個子程序。它會傳回兩個值,一個是子程序的ID,一個是0
if(pid == 0)//在子程序中
{
read(fd, c, 2);
c[2] = '\0';
cout << "---------------------------------------------"<<endl;
cout << c << endl;
gb += 10;
a += 10;
cout << "gb = " << gb << ",a = " << a << endl;
cout << "子程序ID:" << getpid() << ",子程序的父程序ID為:" << getppid() << endl;
cout << "子程序中pthread_self():" << pthread_self() << endl;//因為兩個pthread_self()函數都是在主線程中的,是以兩個擷取的線程ID相同
}
else if(pid > 0)//在目前程序中,也就是父程序中
{
read(fd, c, 2);
c[2] = '\0';
cout << "--------------------------------------------"<<endl;
cout << c << endl;
cout << "gb = " << gb << ",a = " << a << endl;
cout << "父程序ID:" << getpid() << ",父程序的父程序ID為:" << getppid() << endl;
cout<<"父程序中pthread_self():"<<pthread_self()<<endl;//因為兩個pthread_self()函數都是在主線程中的,是以兩個擷取的線程ID相同
}
else
{
cout<<"fork error!"<<endl;
exit(1);
}
close(fd);//關閉檔案描述符對應的檔案,如果關閉成功傳回0,關閉失敗傳回-1
return 0;
}
在linux中執行結果:

這裡我們使用open系統調用打開了一個名為fork.txt的檔案,檔案中的是一個個字元串。
(1)檔案描述符為3:因為系統中0時stdin的檔案描述符,1是stdout的檔案描述符,2是stderr的檔案描述符。其他的用于索引我們自己打開的檔案描述符,每打開一個一個檔案就是使用最小的可使用的檔案描述符表示。如果再打開一個檔案,他的fd是4.
(2)使用getpid()函數可以擷取目前程序的ID,使用getppid()可以擷取目前程序的父程序的ID,使用pthread_self()可以擷取目前線程的ID。
(3)通過結果可以看出我們使用fork建立了子程序并在子程序中對變量gb和a做了修改,但是這個修改并不會影響到父程序中兩個變量的值。這是因為fork系統調用将父程序中的變量拷貝一份給子程序中。父子程序中的資料各不相關。
(4)在父程序中使用read系統調用讀取檔案的前兩個字元ab。然後在子程序中再次讀取兩個字元是cd,而不是ab。這說明父子程序共享同一個檔案,它們對檔案的操作是同步的。