主要函數:
fork 用於創建一個新進程
exit 用於終止進程
exec 用於執行一個程序
wait 將父進程掛起,等待子進程結束
getpid 獲取當前進程的進程ID
nice 改變進程的優先級
---------------------------------
孤兒進程:
如果一個子進程的父進程先於子進程結束,子進程就成為一個孤兒進程,他由init進程收養,成為init進程的子進程。
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
int main() { pid_t pid; pid = fork(); switch( pid ) { case 0: { while(1) { printf("child pid:%d, parent pid:%d\n", getpid(), getppid()); sleep(1); } } case -1: { printf("create child process error\n"); exit(-1); } default: { sleep(3); printf("I am parent,pid:%d\n", getpid()); exit(0); } } return 0; }
child pid:9670, parent pid:9669
child pid:9670, parent pid:9669
child pid:9670, parent pid:9669
I am parent,pid:9669
root@wilson-software:~/Project/xa# child pid:9670, parent pid:1
child pid:9670, parent pid:1
child pid:9670, parent pid:1
child pid:9670, parent pid:1
child pid:9670, parent pid:1
child pid:9670, parent pid:1
從輸出結果來看,父進程停止后,子進程變成了孤兒進程,此時子進程的父進程ID 是 1,
(init進程的進程ID值始終是1)由init進程收養。
------------------------------------------------------------------------------
vfork函數創建一個子進程時,操作系統並不將父進程的地址空間完全復制到子進程,用vfork函數創建的子進程共享父進程的地址空間,
也就是說子進程完全運行在父進程的地址空間上。子進程對該地址空間中任何數據的修改同樣為父進程所見。
使用fork創建一個子進程時,哪個進程先執行取決於系統的調度。
而vfork創建一個子進程時,vfork保證子進程先運行,子進程調用exec或者exit之前父進程處於阻塞等待狀態。
如果在調用exec或者exit之前子進程要依賴父進程的某個行為,就會導致死鎖。
如果創建子進程的目的只是為了調用exec執行某個程序,那么fork過程中子進程對父進程地址空間的復制將會是一個多余的過程。
vfork不會拷貝父進程的地址空間,這大大減小了系統開銷。
使用vfork時要謹慎,最好不要允許子進程修改與父進程共享的全局變量和局部變量
-------------------------------------------------------------------------------------------------------------------------------------------------
父子進程結束的先后順序不同會產生不同的結果:
父進程先退出,子進程后退出,則系統會讓init進程接管子進程。
當子進程先退出,而父進程又沒有調用wait函數等待子進程結束,子進程進入僵死狀態,並且會一直保持下去除非系統重啟。子進程處於僵死狀態時,內核只保存該進程的
一些必要信息以備父進程所需。此時子進程始終占用着資源,同時也減少了系統可以創建的最大進程數。如果子進程先於父進程結束,並且父進程調用了wait或waitpid函數,
則父進程會等待子進程。