(一)fork
#include pid_t fork(void);
返回值:有兩個,乙個是子程序的id,另乙個為零。當返回值為0時,進入子程序,大於0進入父程序,返回-1時建立程序錯誤。子程序與父程序的比較:
(1)子程序與父程序的程序id不同。且父程序id不同。
(2)記憶體布局: 子程序是父程序的副本,其中子程序的資料空間,堆,棧是父程序的副本,但是共享真正文段。
(3)執行順序:子程序與父程序執行順序不確定,取決於核心所使用的排程演算法。
(4)檔案共享:父程序所有開啟的檔案描述符都會賦值到子程序,父程序與子程序每個相同的開啟檔案描述符共享乙個檔案表項。即子程序操作檔案直接影響父程序對該檔案的操作,最明顯的是檔案偏移量收到影響。其圖如下所示:
例如:
#include #include #include int main()
else if( pid == 0 )
wait();
printf("parent: x = %d y = %d\n",x,y);
return 0;
}
fork的使用場景:
(1)父程序希望複製自己,使得父程序和子程序同時執行不同的**段,即在網路服務中是最常見的,父程序等待客戶端的服務請求,當請求到來時,父程序fork乙個子程序來處理子程序的請求,這時父程序可以繼續等待下乙個服務請求。
(2)使得子程序執行乙個不同的程式,需要fork乙個子程序,在此子程序中執行exec執行新的程式。
(二)vfork函式
#include #include pid_t vfork(void);
返回值為:與fork幾乎相同與fork函式的不同:
(1)vfork一般是建立乙個程序來執行exec函式,即執行乙個新的程式。
(2)vfork中,子程序不將父程序的位址空間完全複製到子程序中,其子程序在父程序空間中執行。
(3)vfork保證子程序先執行,父程序等待子程序執行完成後在再執行。
(4)vfork子程序的資源與父程序是共用的,因此父程序中變數經過子程序的對其的改變則父程序也會改變。
例如:
//注意與上個fork的例子進行比較
#include #include #include int main()
else if( pid == 0 )
wait();
printf("parent : x = %d y = %d\n",x,y);
return 0;
}
(三)wait函式#include #include pid_t wait(int *status);
該函式的都是等待子程序的退出,如果成功返回退出程序的id,如果出錯返回-1。
(1)呼叫wait函式
(2)獲得終止狀態
例如:
#include #include #include #include void pr_exit(int status)
else if( wifsignaled(status) ) //判斷該子程序是否異常終止
else if( wifstopped(status) )//子程序暫停
}int main()
else if( pid == 0 )
if( wait(&status) != pid )
pr_exit(status);
if( ( pid = fork()) == -1 )
else if( pid == 0 )
if( wait(&status) != pid )
pr_exit(status);
if( ( pid = fork()) == -1 )
else if( pid == 0 )
if( wait(&status) != pid )
pr_exit(status);
return 0;
}
注意: 如果有多個子程序退出,而需要等待特定的子程序退出時,可以使用wait的返回值與某個期望的id比較。(三)waitpid函式
#include #include pid_t waitpid(pid_t pid, int *status, int
options);
該函式的都是等待特定子程序的退出,如果成功返回退出程序的id,如果出錯返回-1。(1)呼叫waitpid函式
(2)獲得終止狀態與wait相同
(四)exec函式
#include extern char **environ;
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv);
int execle(const char *path, const char *arg,
..., char * const envp);
int execlp(const char *file, const char *arg,
...);
int execvp(const char *file, char *const argv);
int execvpe(const char *file, char *const argv,
char *const envp);
(1)當程序呼叫exec函式時,exec並不建立新的程序,前後id不改變,該程序執行的程式被完全替代為exec新程式,新的程式從main函式開始執行,exec只是用磁碟上的乙個新的程式替換了當前程序的證正文段,資料段,堆段和棧段。(2)函式區別:
例如:
#include #include #include char * env_init = ;
int main()
else if( pid == 0 )
}if( waitpid( pid,null,0) != pid )
if( (pid = fork()) == -1 )
else if( pid == 0 )
}return 0;
}
(五)典型的程序
(1)孤兒程序
產生原因: 父程序終止,子程序會被init程序收養,此時的子程序就是孤兒程序。
產生過程: 程序終止時,核心逐個檢查所有活動程序,以判斷他是否是正要終止程序的子程序,如果是,則該程序的父程序,id就更改為1,這樣就保證了每個程序的都有乙個父程序。
(2)僵死程序
產生原因:乙個程序已經終止,但是其父程序,尚未對其進行善後處理(獲取終止子程序的有關資訊,釋放他仍占用的資源)的程序被稱為僵死程序。父程序沒有等待取得子程序的終止狀態。
避免方法: 核心為每個終止子程序儲存了一定量的資訊,所以當終止程序的父程序呼叫wait或waitpid時,可以得到這些資訊,這些資訊包括程序id,程序的終止狀態,以及程序使用的cpu時間總量。
注意:如果乙個孤兒程序終止時會成為僵死程序麼?:其實是不會的,原因為init程序中的子程序終止時,init會呼叫乙個wait函式取得其終止狀態,這樣可以防止產生僵死程序。
例如:
#include #include #include int main()
else if( pid == 0 )
else
return 0;
}
Linux程序控制程式設計之fork wait
本文將記錄我在學習fork和wait waitpid 這兩個函式的過程。1.fork 在linux中,建立乙個新程序常用fork函式,它非常特別,執行一次,居然返回兩個值,這與一般的函式是大大的不一樣的,這點引起了我高度的注意。prototype pid t fork void return 0 子...
LINUX環境程式設計之程序控制(上)
每個程序都有乙個非負整型表示的唯一程序id。雖然該id是唯一的,但是程序id是可復用的。當乙個程序終止後,其程序id就成為復用的候選者。系統中有一些專用程序,但是具體細節隨實現而不同。id為0的程序通常是排程程序,常常被稱為交換程序。該程序是核心的一部分,它並不執行任何磁碟上的程式,因此也被成為系統...
linux程序控制程式設計
一 程序與程式 程式是放到磁碟的可執行檔案 程序是指程式執行的例項 程序是動態的,程式是靜態的 程式是有序 的集合 程序是程式的執行。通常程序不可在計算機之間遷移 而程式通常對應著檔案 靜態和可以複製。程序是暫時的,程式使長久的 程序是乙個狀態變化的過程,程式可長久儲存。程序與程式組成不同 程序的組...