linux進程包含如下幾個方面:
1:進程的控制(創建,等待子進程終止,執行程序,退出)
2:守護進程(什么是守護進程,守護進程的創建方式)
3:進程間的通信(管道,消息隊列,消息,socket,共享內存)
4:進程間的同步(互斥鎖,信號量,讀寫鎖,文件鎖)
關于fork函數你必須要知道的事情:
fork是一次調用,兩次返回,根據返回值區別是子進程還是父進程。
而且fork生成的子進程是復制父進程的數據空間,棧,堆,以及文件句柄(注意是復制不是共享),所以linux采用COW技術,避免性能的浪費。
還有一個fork的進化版本,vfork函數,該函數用于創建一個子進程,而且該進程會立即執行exec操作,啟動一個新的程序,所以其會共享父進程地址空間(不會產生復制開銷),而且vfork會保證子進程的優先執行,直到其被調用exce或者exit后父進程才能執行。
clone函數可以選擇性的復制父進程的資源,因此clone是創建線程的函數
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
這里fn是函數指針,我們知道進程的4要素,這個就是指向程序的指針, child_stack明顯是為子進程分配系統堆??臻g,flags就是標志用來描述你需要從父進程繼承那些資源, arg就是傳給子進程的參數)。
關于進程的退出:
進程的終止方式比較多,包括函數return返回,或者調用exit退出,
而如果是多線程的進程的話,則最后一個線程的終止或者是調用exit退出會導致進程的退出。
進程的異常終止方式又分為三種:abort函數調用,還有收到異常信號,還有就是最后一個線程對取消請求作出響應。
注意:return函數在系統內部也是調用exit函數,而exit函數再調用_exit函數完成真正的退出操作,_exit不會清理緩沖區,會造成數據流失。
進程調用exit退出,會將退出代碼存儲到PCB中,然后發送SIGCHLD信號給父進程,自身成為僵尸進程,如果父進程調用wait函數則收到信號后會清除子進程的內存空間。
而如果父進程提前退出,則子進程會成為孤兒進程,孤兒進程由init進程托管。而init進程被設置為:無論哪個孤兒進程終止,init進程都會調用wait函數取得其終止狀態,從而防止了大量孤兒進程的產生。
父進程如何知道子進程退出的呢?
父進程可以調用wait函數或者是waitpid函數(二者的區別在于:wait是只要有子進程退出就會處理,而waitpid會等待指定的子進程退出)
而wait函數的過程如下:
如果有子進程已經退出,則立即獲取子進程的退出狀態,并返回。而如果所有子進程都在運行則阻塞等待。如果沒有子進程自然就出錯返回了。
還有一個很重要的函數exec
執行一個新的程序,參數必須有三種:
1:可執行文件路徑
2:參數
3:環境變量
exec族函數有多種變形,其實都是對這三種參數的變化:
比如可執行文件又分為相對路徑和絕對路徑
參數又分為,可以直接傳遞多個變長參數(以空指針結尾)或者是將參數放置于一個數組中。
還有環境變量,可以使用進程原有的環境變量,也可以將環境變量傳遞給函數。
linux的守護進程
什么是守護進程:守護進程隨系統開機而啟動,并且只能在系統關閉時終止,所以守護進程會在系統后臺運行。
如何創建守護進程:看書