Linux_程序的建立
之前瞭解了程序的相關基礎知識,現在來了解一下程序的實際應用
1程序建立的一般過程:
1)給新程序分配一個識別符號。核心中分配一個PCB
2)複製父程序的環境
3)分配程式.資料.棧等記憶體資源
4)複製父程序的地址空間的內容
5)將程序置成就緒狀態,放入就緒佇列
2.fork
1)首先呼叫fork之前,要加標頭檔案#include <unistd.h>
2)函式原型 pid_t fork(void)
3)返回值:子程序返回0,父程序返回子程序id,出錯返回-1,建立子程序失敗。
4)fork呼叫失敗原因:系統內有太多程序或者實際使用者的程序數超過了限制。
下面驗證一下fork()的返回值
圖中箭頭和數字代表程式執行步驟
執行結果:
解釋一下:程式開始執行,首先進入父程序,在呼叫fork之前,先輸出父程序的id,執行fork後,父子程序會從fork之後的程式碼來繼續執行,繼續執行父程序,pid接受fork返回值,父程序返回子程序id,然後進入子程序,pid接收fork返回值,子程序返回0。
注意:
1)父子程序執行先後順序不確定
2)呼叫fork以後,父子程序交替執行。
3)如果父程序先死,子程序就變成孤兒程序,孤兒程序會被1號程序收養。
4)如果子程序先死,子程序就會變成殭屍程序(清理殭屍程序,用wait函式)
另一種執行步驟:(fork後先執行子程序)
3.子程序與父程序
子程序繼承父程序:
地址空間,程序上下文,程序堆疊,記憶體資訊,檔案描述符(父程序開啟的檔案),訊號設定,程序排程優先順序,當前路徑,根路徑,控制終端,程序組,資源限制情況...
子程序不繼承父程序:
1>父程序的鎖子程序不繼承
2>父程序id子程序不繼承
3>父程序未決的訊號子程序不繼承
4>父程序的鬧鐘子程序不繼承
子程序與父程序的關係:
子程序以父程序為模板,首先複製父程序的PCB,並進行簡單修改;複製父程序的虛擬地址空間(頁表)對應的實體記憶體會進行寫時拷貝。
4.vfork
1)首先呼叫vfork之前,要加標頭檔案#include <unistd.h> 和 #include <sys/types.h>
2)函式原型 pid_t vfork(void)
vfork 與fork的區別
1)vfork用於建立一個子程序,創建出來的子程序和父程序共用同一塊虛擬空間。但fork出來的子程序具有獨立的地址空間。
2)vfork出來的子程序一定會先執行,父程序會掛起,一直掛起到子程序呼叫了_exit或exec父程序才會繼續執行。
例項:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int glob=100;
int main(void){
pid_t pid;
pid = vfork();
if(pid==-1) perror("fork"),exit(1);
else if(pid ==0) {//子程序
sleep(3);
glob=200;
printf("child glob %d \n",glob);
exit(0);
}
else { //父程序
printf("parent glob %d \n",glob);
}
return 0;
}
執行結果:
解釋一下:子程序先執行,修改了glob變數的值,呼叫了exit,父程序排程執行,父子程序共用一塊虛擬記憶體,所以glob的值也被更改。