一、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;
}
從中可以看書父進程是在等子進程執行完畢後纔開始執行的。