一、fork函式
要建立一個程式,最基本的系統呼叫是fork,系統呼叫fork用於派生一個程式,函式原型如下: pid_t fork(void) 若成功,父程式中返回子程式ID,子程式中返回0,若出錯返回-1;fork()系統呼叫的作用是複製一個程式,當一個程式呼叫它,完成個就出現兩個幾乎一摸一樣的程式,新程式是子程式,原來的程式是父程式。子程式是父程式的一個拷貝,子程式從父程式那裡得到了程式碼段和資料段的拷貝。Fork函式呼叫一次,但返回兩次,兩次返回的區別是子程式的返回值是0,父程式的返回值是子程式返回值的程式ID。Fork返回後,子程式和父程式都從呼叫fork函式的下一條語句開始執行。
程式一是fork呼叫:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 0;
pid_t pid; /*此時僅有一個程式*/
pid = fork(); /*此時已經有兩個程式在同時執行*/
if(pid < 0)
{
printf("error in fork!");
exit(1); /* fork出錯退出*/
}
else if(pid==0)
printf("I am the child process, the count is %d, my process ID is %d\n",count,getpid());
else
printf("I am the parent process, the count is %d, my process ID is %d\n",++count,getpid());
return 0;
}
必須瞭解一個概念:在語句pid = fork();之前,只有一個程式在執行這段程式碼,該語句之後,就變成兩個程式在執行了,且二者程式碼部分完全相同,將要執行的下一條語句都是 if(pid<0)。
Fork函式的奇妙之處是僅僅被呼叫一次,卻返回了兩次,可能有三種取值:
1,在父程式中,fork返回新建立子程式的ID
2,在子程式中,fork返回0
3,出現錯誤時,返回負值
二、linux下另一個建立程式的方式是vfork,原型如下:pid_t vfork(void);
若成功,父程式中返回子程式ID,子程式中返回0,若出錯返回-1;fork與vfork是有區別的,fork要拷貝父程式的資料段,而vfork不需要完全拷貝父程式的資料段,在子程式沒有呼叫exec或者exit函式之前,子程式會與父程式共享資料段。在fork中子程式與父程式的執行順序不確定,而在vfork中,子程式先執行,父程式掛起,直到子程式呼叫了exec或者exit函式,父程式才被執行。
程式二說明了vfork建立後父子程式是共享資料段的。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 1;
int child;
printf("Before create son, the father's count is:%d\n", count); /*建立程式之前*/
child = vfork(); /*此時已經有兩個程式在同時執行*/
if(child < 0)
{
printf("error in vfork!");
exit(1); /* fork出錯退出*/
}
if(child==0) /*子程式*/
{
printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(1);
}
else /*父程式*/
{
printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child);
}
return 0;
}
在子程式中修改了count值,在父程式中輸出count時是子程式修改後的值,這說明父程式和子程式是共享count,也就是二者是共享記憶體區的。
程式三說明由vfork創造出來的子程式是會導致父程式掛起,直到子程式執行xec或者exit函式才會喚醒父程式
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 1;
int child;
printf("Before create son, the father's count is:%d\n", count); /*建立程式之前*/
if(!(child = vfork()))
{ /*這裡是子程式執行區*/
int i;
for(i = 0; i < 100; i++)
{
printf("This is son, The i is: %d\n", i);
if(i == 70)
exit(1);
}
printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(1); /*子程式退出*/
}
else
{ /*父程式執行區*/
printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child);
}
return 0;
}
從中可以看書父程式是在等子程式執行完畢後才開始執行的。