任務描述
在上一關我們學習如何獲取進程的pid
信息,本關我們將介紹如何編程創(chuàng)建一個新的進程。
本關任務:學會使用C
語言在Linux
系統(tǒng)中使用fork
系統(tǒng)調(diào)用創(chuàng)建一個新的進程。
相關知識
在Linux
系統(tǒng)中創(chuàng)建進程有很多函數(shù)可以使用,其中包括了系統(tǒng)調(diào)用也包括庫函數(shù)。本關將介紹一個最常見的系統(tǒng)調(diào)用函數(shù)來創(chuàng)建進程,這就是使用fork
函數(shù)來創(chuàng)建一個新進程。
當用戶調(diào)用fork
函數(shù)時,系統(tǒng)將會創(chuàng)建一個與當前進程相同的新進程。通常將原始進程稱為父進程,而把新生成的進程稱為子進程。子進程是父進程的一個拷貝,子進程獲得同父進程相同的數(shù)據(jù),但是同父進程使用不同的數(shù)據(jù)段和堆棧段。
在早期的系統(tǒng)中,創(chuàng)建進程比較簡單。當調(diào)用fork
時,內(nèi)核會把所有的內(nèi)部數(shù)據(jù)結構復制一份,復制進程的頁表項,然后把父進程的地址空間中的內(nèi)容也復制到子進程的地址空間中。但是從內(nèi)核角度來說,這種復制方式是非常耗時的。
因此,在現(xiàn)代的系統(tǒng)中采取了更多的優(yōu)化?,F(xiàn)代的Linux
系統(tǒng)采用了寫時復制技術(Copy on Write
),而不是一創(chuàng)建子進程就將所有的數(shù)據(jù)都復制一份。
Copy on Write
(COW
)的主要思路是:如果子進程/父進程只是讀取數(shù)據(jù),而不是對數(shù)據(jù)進行修改,那么復制所有的數(shù)據(jù)是不必要的。因此,子進程/父進程只要保存一個指向該數(shù)據(jù)的指針就可以了。當子進程/父進程要去修改數(shù)據(jù)時,那么再復制該部分數(shù)據(jù)即可。這樣也不會影響到子父進程的執(zhí)行。因此,在執(zhí)行fork
時,子進程首先只復制一個頁表項,當子進程/父進程有寫操作時,才會對所有的數(shù)據(jù)塊進行復制操作。
[COW
思路]
在Linux
系統(tǒng)中可以使用man
命令來查詢該函數(shù)的使用方法。具體的查詢命令為: man 2 函數(shù)名
使用fork函數(shù)創(chuàng)建進程
fork
函數(shù)的具體的說明如下:
-
需要的頭文件如下:
#include <unistd.h>
-
函數(shù)格式如下:
pid_t fork(void);
-
函數(shù)返回值說明: 調(diào)用成功,
fork
函數(shù)兩個值,分別是0
和子進程ID
號。當調(diào)用失敗時,返回-1
,并設置錯誤編號errno
。
注意:fork
函數(shù)調(diào)用將執(zhí)行兩次返回,它將從父進程和子進程中分別返回。從父進程返回時的返回值為子進程的 PID
,,而從子進程返回時的返回值為0
,并且返回都將執(zhí)行fork
之后的語句。
案例演示1: 編寫一個程序,使用fork
函數(shù)創(chuàng)建一個新進程,并在子進程中打印出其進程ID
和父進程ID
,在父進程中返回進程ID
。詳細代碼如下所示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main()
{
pid_t pid;
pid = fork();
if(pid == -1)
{
//創(chuàng)建進程失敗
printf("創(chuàng)建進程失敗(%s)!\n", strerror(errno));
return -1;
}
else if(pid == 0)
{
//子進程
printf("當前進程為子進程:pid(%d),ppid(%d)\n", getpid(), getppid());
}
else
{
//父進程
printf("當前進程為父進程:pid(%d),ppid(%d)\n", getpid(), getppid());
}
//子進程和父進程分別會執(zhí)行的內(nèi)容
return 0;
}
將以上代碼保存為forkProcess.c
文件,編譯執(zhí)行??梢钥吹矫看螆?zhí)行forkProcess
時,子進程和父進程都不是固定的執(zhí)行順序,因此由fork
函數(shù)創(chuàng)建的子進程執(zhí)行順序是由操作系統(tǒng)調(diào)度器來選擇執(zhí)行的。因此,子進程和父進行在執(zhí)行的時候順序不固定。
編程要求
本關的編程任務是補全右側代碼片段中Begin
至End
中間的代碼,具體要求如下:
- 補全
createProcess
函數(shù),使用fork
函數(shù)創(chuàng)建進程,并在子進程中輸出"Children"
字符串,在父進程中輸出"Parent"
字符串。(注意:不要在createProcess
函數(shù)中使用exit
函數(shù)或者return
來退出程序)。
測試說明
本關的測試需要用戶在右側代碼頁中補全代碼,然后點擊評測按鈕,平臺會自動驗證用戶是否按照要求去檢測結果。文章來源:http://www.zghlxwxcb.cn/news/detail-464168.html
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
/************************
* 提示: 不要在子進程或父進程中使用exit函數(shù)或者return來退出程序
*************************/
void createProcess()
{
/********** BEGIN **********/
pid_t pid=fork();
if(pid==-1)
{
printf("創(chuàng)建進程失敗(%s)!\n", strerror(errno));
}
else if(!pid)
{
printf("Children",getpid(),getppid());
}
else
{
printf("Parent",getpid(),getppid());
}
/********** END **********/
}
?第三關鏈接--頭歌(Linux之進程管理一):第3關:進程創(chuàng)建操作-vfork_小妞無語的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-464168.html
到了這里,關于頭歌(Linux之進程管理一):第2關:進程創(chuàng)建操作-fork的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!