FORK()函數的理解
對于剛剛接觸Unix/Linux操作系統,在Linux下編寫(xiě)多進(jìn)程的人來(lái)說(shuō),fork是最難理解的概念之一:它執行一次卻返回兩個(gè)值。
本文引用地址:http://dyxdggzs.com/article/148649.htm首先我們來(lái)看下fork函數的原型:
#i nclude
#i nclude
pid_t fork(void);
返回值:
負數:如果出錯,則fork()返回-1,此時(shí)沒(méi)有創(chuàng )建新的進(jìn)程。最初的進(jìn)程仍然運行。
零:在子進(jìn)程中,fork()返回0
正數:在負進(jìn)程中,fork()返回正的子進(jìn)程的PID
其次我們來(lái)看下如何利用fork創(chuàng )建子進(jìn)程。
創(chuàng )建子進(jìn)程的樣板代碼如下所示:
pid_t child;
if((child = fork())0)
/*錯誤處理*/
else if(child == 0)
/*這是新進(jìn)程*/
else
/*這是最初的父進(jìn)程*/
fock函數調用一次卻返回兩次;向父進(jìn)程返回子進(jìn)程的ID,向子進(jìn)程中返回0,
這是因為父進(jìn)程可能存在很多過(guò)子進(jìn)程,所以必須通過(guò)這個(gè)返回的子進(jìn)程ID來(lái)跟蹤子進(jìn)程,
而子進(jìn)程只有一個(gè)父進(jìn)程,他的ID可以通過(guò)getppid取得。
下面我們來(lái)對比一下兩個(gè)例子:
第一個(gè):
#include
#include
int main()
{
pid_t pid;
int count=0;
pid = fork();
printf( This is first time, pid = %dn, pid );
printf( This is secONd time, pid = %dn, pid );
count++;
printf( count = %dn, count );
if ( pid>0 )
{
printf( This is the parent process,the child has the pid:%dn, pid );
}
else if ( !pid )
{
printf( This is the child Process.n)
}
else
{
printf( fork failed.n );
}
printf( This is third time, pid = %dn, pid );
printf( This is fouth time, pid = %dn, pid );
return 0;
}
運行結果如下:

問(wèn)題:
這個(gè)結果很奇怪了,為什么printf的語(yǔ)句執行兩次,而那句“count++;”的語(yǔ)句卻只執行了一次
接著(zhù)看:
#include
#include
int main(void)
{
pid_t pid;
int count=0;
pid = fork();
printf( Now, the pid returned by calling fork() is %dn, pid );
if ( pid>0 )
{
printf( This is the parent procESS,the child has the pid:%dn, pid );
printf( In the parent process,count = %dn, count );
}
else if ( !pid )
{
printf( This is the child process.n);
printf( Do your own things here.n );
count ++;
printf( In the child process, count = %dn, count );
}
else
{
printf( fork failed.n );
}
return 0;
}
運行結果如下:
現在來(lái)解釋上面提出的問(wèn)題。
看這個(gè)程序的時(shí)候,頭腦中必須首先了解一個(gè)概念:在語(yǔ)句pid=fork()之前,只有一個(gè)進(jìn)程在執行這段代碼,但在這條語(yǔ)句之后,就變成兩個(gè)進(jìn)程在執行了,這兩個(gè)進(jìn)程的代碼部分完全相同,將要執行的下一條語(yǔ)句都是if ( pid>0 )……。
兩個(gè)進(jìn)程中,原先就存在的那個(gè)被稱(chēng)作“父進(jìn)程”,新出現的那個(gè)被稱(chēng)作“子進(jìn)程”。父子進(jìn)程的區別除了進(jìn)程標志符(process ID)不同外,變量pid的值也不相同,pid存放的是fork的返回值。fork調用的一個(gè)奇妙之處就是它僅僅被調用一次,卻能夠返回兩次,它可能有三種不同的返回值:
1. 在父進(jìn)程中,fork返回新創(chuàng )建子進(jìn)程的進(jìn)程ID;
2.在子進(jìn)程中,fork返回0;
3.如果出現錯誤,fork返回一個(gè)負值;
fork出錯可能有兩種原因:(1)當前的進(jìn)程數已經(jīng)達到了系統規定的上限,這時(shí)errno的值被設置為EAGAIN。(2)系統內存不足,這時(shí)errno的值被設置為ENOMEM。
接下來(lái)我們來(lái)看看APUE2中對fork的說(shuō)明:
The new process created by fork is called the child process. This function is called once but returns twice. The only difference in the returns is that the return value in the child is 0, whereas the return value in the parent is the process ID of the new child. The reason the child's process ID is returned to the parent is that a process can have more than one child, and there is no function that allows a process to o^ain the process IDs of its children. The reason fork returns 0 to the child is that a process can have only a single parent, and the child can always call getppid to o^ain the process ID of its parent. (Process ID 0 is reserved for use by the kernel, so it's not possible for 0 to be the process ID of a child.)
被fork創(chuàng )建的新進(jìn)程叫做自進(jìn)程。fork函數被調用一次,卻兩次返回。返回值唯一的區別是在子進(jìn)程中返回0,而在父進(jìn)程中返回子進(jìn)程的pid。在父進(jìn)程中要返回子進(jìn)程的pid的原因是父進(jìn)程可能有不止一個(gè)子進(jìn)程,而一個(gè)進(jìn)程又沒(méi)有任何函數可以得到他的子進(jìn)程的pid。
Both the child and the parent continue executing with the instruction that follows the call to fork. The child is a copy of the parent. For example, the child gets a copy of the parent's data space, heap, and stack. Note that this is a copy for the child; the parent and the child do not share these portions of memory. The parent and the child share the text segment (Section 7.6).
pid控制相關(guān)文章:pid控制原理
評論