本章介紹在Unix系統中對進程的控制,包括創建進程、執行程序、進程中止等。
還介紹了進程的各種屬性,如進程ID。
1.進程標識符(Process identifier)
每個進程有一個唯一的非負標識號,進程ID。
幾個特殊的進程:
ID=0的進程:通常是調度進程Scheduler Process,或者叫Swapper。它是內核的一部分,作為系統進程運行
ID=1的進程:通常是init進程,程序位於/sbin/init,負責啟動Unix系統。 init通過讀取系統初始化文件(/etc/rc*)將系統啟動到指定的運行級別。
init進程不會結束。如果父進程在子進程終止之前就結束了,則該父進程的所有子進程的父進程ID被修改為1,即init進程,以保證所有進程都有父進程。
2.fork函數
Unix系統產生新進程的唯一方法:調用fork()函數
#include \
#include \
pid_t fork(void); return 0 in child , process ID of child in parent, -1 on error
3.文件共享
由於fork函數復制了父進程的文件打開表給子進程,故具有父子關系的進程將共享打開文件。見下圖
注意與獨立進程間(不是父子關系進程)文件共享的區別!
父子進程共享了文件表(上圖中間一欄),所以不論是誰修改了文件,文件偏移量的修改對雙方都是有效的。
獨立進程間的文件共享是共享的V-node結構(上圖第三欄),所以進程間擁有各自不同的當前文件偏移量,這點注意。
3。vfork函數
vfork和fork的功能基本一致,均是創建創建一個新進程。但是有兩點不同:
a) vfork創建的新進程專門用於執行新的程序,所以它不會全部復制父進程地址空間內的所有信息給子進程。通常調用vfork後,子進程將緊跟著調用exec
b) vfork保證子進程首先運行,父進程掛起,直至子進程調用exec或exit,父進程才重新運行
4。wait 和 waitpid函數
當一個進程結束的時候,內核將發送一個SIGCHLD信號給其父進程。下面兩個函數用於父進程等待子進程結束
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
both return process ID if OK, 0 and -1 on error
參數說明:
int *statloc用於存儲結束進程的終止狀態。但如果我們不關心子進程的結束狀態,可以給null指針。
pid_t pid : waitpid指定等待進程的ID號。
若指定pid=-1,則其功能與wait一致,相當於無阻塞版的wait
兩者區別:
wait將阻塞調用進程,直至該進程任何一個子進程結束。但如果該進程有僵屍子進程,則wait函數將立即返回,statloc存放該僵屍進程的終止狀態。
(僵屍進程,zombie process,指已經結束的進程,但其父進程並未獲取其終止狀態,釋放資源等操作的進程)
waitpid等待process id為pid的子進程結束。即利用該函數可以撲獲指定的進程結束的狀態,但是並不阻塞調用者
5。exec函數
前面提到vfork,創建的子進程用於執行新的程序,共有六種形式的exec
記憶方法:
l : 表示使用參數列表(list)
e:表示使用新的環境變量,不從當前繼承
p: 表示使用文件名,並從PATH環境進行搜索
6. System函數
利用System函數可以在程序中方便的調用shell命令.
例如,想向一個文件中保存當前時間,可以很容易實現 System("date > file");
System函數原形為 :
int system(const char *cmdstring);
system函數由fork,exec,waitpid來實現