fork在英文中是“分叉”的意思,為什么取這個名字呢?因為一個行程在運行中,如果使用了fork函式,就產生了另一個行程,于是行程就“分叉”了,所以這個名字取得很形象,下面就看看如何具體使用fork函式,這段程式演示了使用fork的基本框架, 函式宣告: pid_t fork(); fork函式用于產生一個新的行程,函式回傳值pid_t是一個整數,在父行程中,回傳值是子行程編號,在子行程中,回傳值是0,
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { printf("本程式的行程編號是:%d\n",getpid()); int ipid=fork(); sleep(1); // sleep等待行程的生成, printf("pid=%d\n",ipid); if (ipid!=0) printf("父行程編號是:%d\n",getpid()); else printf("子行程編號是:%d\n",getpid()); sleep(30); // 是為了方便查看行程在shell下用ps -ef|grep book252查看本行程的編號, }從 fork() 這個函式開始出現后, 便創建了子行程,并且子行程和父行程一樣從fork(這個函式一起執行下去,也就是說從fork()開始的下面所有代碼分別被父 行程和子行程都執行了一次,如果沒有條件判斷陳述句判別fork()的回傳值,將無法分別子父行程,根據fork()的回傳值可以令子父行程跳過或執行某條陳述句
運行結果

初學者可能用點接受不了現實,
1)一個函式(fork)回傳了兩個值?
2)if和else中的代碼能同時被執行?
那么呼叫這個fork函式時發生了什么呢?fork函式創建了一個新的行程,新行程(子行程)與原有的行程(父行程)一模一樣,子行程和父行程使用相同的代碼段;子行程拷貝了父行程的堆疊段和資料段,子行程一旦開始運行,它復制了父行程的一切資料,然后各自運行,相互之間沒有影響,
fork函式對回傳值做了特別的處理,呼叫fork函式之后,在子程式中fork的回傳值是0,在父行程中fork的回傳是子行程的編號,程式員可以通過fork的回傳值來區分父行程和子行程,然后再執行不同的代碼,
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> void fatchfunc() // 父行程流程的主函式 { printf("我是老子,我喜歡孩子他娘,\n"); } void childfunc() // 子行程流程的主函式 { printf("我是兒子,我喜歡西施,\n"); } int main() { if (fork() > 0) { printf("這是父行程,將呼叫fatchfunc(),\n"); fatchfunc(); } else { printf("這是子行程,將呼叫childfunc(),\n"); childfunc(); } sleep(1); printf("父子行程執行完自己的函式后都來這里,\n"); sleep(1); }
運行結果:

在上文上已提到過,子行程拷貝了父行程的堆疊段和資料段,也就是說,在父行程中定義的變數子行程中會復制一個副本,fork之后,子行程對變數的操作不會影響父行程,父行程對變數的操作也不會影響子行程,
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int i=10; int main() { int j=20; if (fork()>0) //從 fork() 這個函式開始出現后, //便創建了子行程并且和父行程一樣從fork() //這個函式一起執行下去,也就是說從fork()開始的下面所有代碼分別被父///行程和子行程都執行了一次,如果沒有條件判斷陳述句判別fork()的回傳/////值,將無法分別子父行程,根據fork()的回傳值可以令子父行程跳過或執///行某條陳述句 { //如果fork大于零,證明是父行程,即執行下面的陳述句 i=11;j=1; sleep(1); printf("父行程:i=%d,j=%d\n",i,j); int sum = i + j; printf("父sum = %d\n",sum); } else { //如果fork小于零,證明是子行程,執行下面的陳述句 i=12;j=22; sleep(1); printf("子行程:i=%d,j=%d\n",i,j); printf("子sum = %d\n",i+j); } }從 fork() 這個函式開始出現后,便創建了子行程,并且子行程和父行程一樣從fork(這個函式一起執行下去,也就是說從fork()開始的下面所有代碼分別被父 行程和子行程都執行了一次,如果沒有條件判斷陳述句判別fork()的回傳值,將無法分別子父行程,根據fork()的回傳值可以令子父行程跳過或執行某條陳述句
運行結果

來源:www.freecplus.net
作者:碼農有道
作業:
(1)撰寫一個多行程程式,驗證子行程是復制父行程的記憶體變數,還是父子行程共享記憶體變數?
復制記憶體變數
2)撰寫一個示例程式,由父行程生成10個子行程,在子行程中顯示它是第幾個子行程和子行程本身的行程編號,
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { int i = 0; while (i < 10) { if (fork() > 0) { i++; continue; //父行程回到while(回圈), } else { printf("子行程第%d個,pid = %d\n", i, getpid()); break; } } sleep(10); return 0; }
運行結果


3)撰寫示例程式,由父行程生成子行程,子行程再生成孫行程,共生成第10代行程,在各級子行程中顯示它是第幾代子行程和子行程本身的行程編號,
如圖
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { int i = 0; //全域變數,計數器,計算第幾代子行程 while (i < 10) { if (fork()== 0) { i++; continue; } else { printf("第%d代子行程,pid = %d\n", i, getpid()); 第 0 代子行程是第一個父行程 break; } } sleep(10); return 0; }
運行結果:

子行程是下一個子行程的父行程

4)利用盡可能少的代碼快速fork出更多的行程,試試看能不能把linux系統搞死,
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { int i = 0; //全域變數,計數器,計算第幾代子行程 while (i < 10) { if (fork()>0) { fork(); } } printf("pid=%d",getpid()); return 0; }


5)ps -ef |grep book251命令是ps和grep兩個系統命令的組合,各位查一下資料,了解一下grep命令的功能,對程式員來,grep是經常用到的命令,
https://blog.csdn.net/weixin_52273136/article/details/110451596
來源:C語言技術網(www.freecplus.net)
作者:碼農有道
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/474571.html
標籤:C++
