在linux中,啟動並執行一個進程,會佔去linux的三個地方,代碼區,堆棧區和資料區.如果同時運行多個相同的程式,他們就會使用相同的代碼區,代碼區中存放的就程式的代碼,但是資料區和堆棧區分別存放的是程式的資料,全域變數和局部變數,因此即使是相同的程式,也不可同時使用相同的資料和堆棧區.
#include<stdio.h>
#include<unistd.h>
int main()
{
if(fork() == 0)
{
printf("First./n");
if(fork() == 0)
{
printf("Second./n");
}
else
{
printf("Third./n");
}
}
else
{
printf("Fourth./n");
if(fork() == 0)
{
printf("Fivth./n");
}
else
{
printf("Sixth./n");
}
}
}
可以關注下程式的運行結果,以及輸出的順序,並理解為什麼是這種輸出結果.
fork()函數:
程式調用fork()函數,系統就為新的進程準備了堆棧區,資料區和代碼區.系統先讓fork()出的進程和原先的進程使用同一個代碼區.那麼資料區和堆棧區就不能共用了,因此系統會複製一份完全一抹一樣的給fork()出的那個進程.這樣父進程的所有資料就給了子進程.這樣子進程開始運行時,雖然複製了父進程的資料和堆棧,但是資料和堆棧已經分開了,相互之間已經沒有影響了.對於父進程,fork()函數返回了子進程的進程號,對於子進程,fork()函數則返回0,因此根據fork()函數的傳回值就能知道,程式現在處的位置是在子進程中還是在父進程中.
也就是傳說中的,一個函數具有兩個傳回值,就是指fork()函數.
那麼引來一個問題...如何在一個進程中讓另外一個進程啟動呢..?
在linux中,基本上使用exec類的函數,但是exec類函數的使用有一個特點就是:一旦你使用exec類的函數,原先的進程就廢掉了,因為程式碼片段會被新的進程佔據,資料區和堆棧區也會被廢掉,併產生新的資料區和堆棧區供新的進程使用.唯一沒有變的就是進程號,實際上,只有PID是一樣的,其他的東西已經物是人非了.對系統而言,還是同一個進程,因為系統只認進程號,而對編程而言,已經完全是一個新的進程了.
那麼...又來了...
如果你想繼續原先的進程運行,並且同時啟動新的進程..要怎麼辦..?
看上面我給的代碼...對了..就是利用fork()函數和exec類的函數搭配使用.
fork()出一個和父進程完全一抹一樣的進程,然後再使用exec類函數來啟動新的進程,這樣,原先的進程也在運行,新的進程也在運行了.只不過,區別是,現在的關係變成了父進程和子進程的關係了,而不是原來的同一個進程的關係.