舉例講解C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的用法
先來看這樣一個例子,利用fork調(diào)用execlp()函數(shù)來在Linux下實現(xiàn)ps或ls命令:
#include "sys/types.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
pid_t result;
result=fork();
//報錯處理
if(result==-1)
{
printf("Fork Error\n");
}
//son
else if(result==0)
{//調(diào)用execlp()函數(shù),相當(dāng)于"ps -ef"
if((result=execlp("ps","ps",NULL))<0);
printf("son\n");
}
//father
else
{
if((result=execlp("ls","ls",NULL))<0);
printf("father\n");
}
}
一般來講, 我們編寫1個普通的c程序, 運(yùn)行這個程序直到程序結(jié)束, 系統(tǒng)只會分配1個pid給這個程序, 也就就說, 系統(tǒng)里只會有一條關(guān)于這個程序的進(jìn)程.
但是執(zhí)行了fork() 這個函數(shù)就不同了.
fork 這個英文單詞在英文里是"分叉"意思, fork() 這個函數(shù)作用也很符合這個意思. 它的作用是復(fù)制當(dāng)前進(jìn)程(包括進(jìn)程在內(nèi)存里的堆棧數(shù)據(jù))為1個新的鏡像. 然后這個新的鏡像和舊的進(jìn)程同時執(zhí)行下去. 相當(dāng)于本來1個進(jìn)程, 遇到fork() 函數(shù)后就分叉成兩個進(jìn)程同時執(zhí)行了. 而且這兩個進(jìn)程是互不影響
參考下面這個小程序:
int fork_3(){
printf("it's the main process step 1!!\n\n");
fork();
printf("step2 after fork() !!\n\n");
int i; scanf("%d",&i); //prevent exiting
return 0;
}
在這個函數(shù)里, 共有兩條printf語句, 但是執(zhí)行執(zhí)行時則打出了3行信息. 如下圖:

為什么呢, 因為fork()函數(shù)將這個程序分叉了啊, 見下面的圖解:

可以見到程序在fork()函數(shù)執(zhí)行時都只有1條主進(jìn)程, 所以 step 1 會被打印輸出1次.
執(zhí)行 fork()函數(shù)后, 程序分叉成為了兩個進(jìn)程, 1個是原來的主進(jìn)程, 另1個是新的子進(jìn)程, 它們都會執(zhí)行fork() 函數(shù)后面的代碼, 所以 step2 會被 兩條進(jìn)程分別打印輸出各一次, 屏幕上就總共3條printf 語句了!
可以見到這個函數(shù)最后面我用了 scanf()函數(shù)來防止程序退出, 這時查看系統(tǒng)的進(jìn)程, 就會發(fā)現(xiàn)兩個相同名字的進(jìn)程:

如上圖, pid 8808 那個就是主進(jìn)程了, 而 pid 8809那個就是子進(jìn)程啊, 因為它的parent pid是 8808啊!
需要注意的是, 假如沒有做特殊處理, 子進(jìn)程會一直存在, 即使fork_3()函數(shù)被調(diào)用完成, 子進(jìn)程會和主程序一樣,返回調(diào)用fork_3() 函數(shù)的上一級函數(shù)繼續(xù)執(zhí)行, 直到整個程序退出.
可以看出, 假如fork_3() 被執(zhí)行2次, 主程序就會分叉兩次, 最終變成4個進(jìn)程, 是不是有點(diǎn)危險. 所以上面所謂的特殊處理很重要啊!
區(qū)別分主程序和子程序
實際應(yīng)用中, 單純讓程序分叉意義不大, 我們新增一個子程序, 很可能是為了讓子進(jìn)程單獨(dú)執(zhí)行一段代碼. 實現(xiàn)與主進(jìn)程不同的功能.
要實現(xiàn)上面所說的功能, 實際上就是讓子進(jìn)程和主進(jìn)程執(zhí)行不同的代碼啊.
所以fork() 實際上有返回值, 而且在兩條進(jìn)程中的返回值是不同的, 在主進(jìn)程里 fork()函數(shù)會返回主進(jìn)程的pid, 而在子進(jìn)程里會返回0! 所以我們可以根據(jù)fork() 的返回值來判斷進(jìn)程到底是哪個進(jìn)程, 就可以利用if 語句來執(zhí)行不同的代碼了!
如下面這個小程序fork_1():
int fork_1(){
int childpid;
int i;
if (fork() == 0){
//child process
for (i=1; i<=8; i++){
printf("This is child process\n");
}
}else{
//parent process
for(i=1; i<=8; i++){
printf("This is parent process\n");
}
}
printf("step2 after fork() !!\n\n");
}
我對fork() 函數(shù)的返回值進(jìn)行了判斷, 如果 返回值是0, 我就讓認(rèn)為它是子進(jìn)程, 否則是主程序. 那么我就可以讓這兩條進(jìn)程輸出不同的信息了.
輸出信息如下圖:

可以見到 子程序和主程序分別輸出了8條不同的信息, 但是它們并不是規(guī)則交替輸出的, 因為它們兩條進(jìn)程是互相平行影響的, 誰的手快就在屏幕上先輸出, 每次運(yùn)行的結(jié)果都有可能不同哦.
下面是圖解:

由圖解知兩條進(jìn)程都對fork()返回值執(zhí)行判斷, 在if 判斷語句中分別執(zhí)行各自的代碼. 但是if判斷完成后, 還是會回各自執(zhí)行接下來的代碼. 所以 step2 還是輸出了2次.
相關(guān)文章
C++實現(xiàn)LeetCode(188.買賣股票的最佳時間之四)
這篇文章主要介紹了C++實現(xiàn)LeetCode(188.買賣股票的最佳時間之四),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

