進程進階
1.進程鎖
這裏的進程鎖與線程鎖、互斥量、讀寫鎖和自旋鎖不同,它是通過記錄一個PID文件,避免兩個進程同時運行的文件鎖。
2.各種進程的概念
(1)孤兒進程
孤兒進程指的是在其父進程執行完成或被終止後仍繼續運行的一類進程。
孤兒進程與殭屍進程是完全不同的,後面會詳細介紹殭屍進程。而孤兒進程借用了現實中孤兒的概念,也就是父進程不在了,子進程還在運行,這時我們就把子進程的PPID設爲1。前面講PID提到,操作系統會創建進程號爲1的init進程,它沒有父進程也不會退出,可以收養系統的孤兒進程。
(2)殭屍進程
當一個進程完成它的工作終止之後,它的父進程需要調用wait()或者waitpid()系統調用取得子進程的終止狀態。
一個進程使用fork創建子進程,如果子進程退出,而父進程並沒有調用wait或waitpid獲取子進程的狀態信息,那麼子進程的進程描述符仍然保存在系統中。這種進程稱之爲殭屍進程。
(3)守護進程
可以認爲守護進程就是後臺服務進程,因爲它會有一個很長的生命週期提供服務,關閉終端不會影響服務,也就是說可以忽略某些信號。
3.進程間通信
IPC全稱Interprocess Communication,指進程間協作的各種方法,當然包括共享內存,信號量或Socket等。
進程間通信有以下幾種方式:
(1)管道
管道是進程間通信最簡單的方式,任何進程的標準輸出都可以作爲其他進程的輸入。
(2)信號
(3)消息隊列
(4)共享內存
(5)信號量
信號量本質上是一個整型計數器,調用wait時計數減一,減到零開始阻塞進程,從而達到進程、線程間協作的作用。
(6)socket
也就是通過網絡來通信,這也是最通用的IPC,不要求進程在同一臺服務器上。
4.信號
信號只是告訴進程發生了什麼事件,而不會傳遞任何數據。
例子:
import os/signal
siganl.Notify()
signal.Stop()
5.文件描述符
Linux很重要的設計思想就是一切皆文件,網絡是文件,鍵盤等外設也是文件。
內核給每個訪問的文件分配了文件描述符(File Descriptor),它本質是一個非負整數,在打開或新建文件時返回,以後讀寫文件都要通過這個文件描述符了。
6.epoll
Epoll是poll的改進版,更加高效,能同時處理大量文件描述符,跟高併發有關。
重點看看epoll,它大幅提升了高併發服務器的資源使用率,相比poll而言哦。前面提到poll會輪詢整個文件描述符集合,而epoll可以做到只查詢被內核IO事件喚醒的集合,當然它還提供邊沿觸發(Edge Triggered)等特性。
C10K問題,指的是服務器如何支持同時一萬個連接的問題。如果是一萬個連接就有至少一萬個文件描述符,poll的效率也隨文件描述符的更加而下降,epoll不存在這個問題是因爲它僅關注活躍的socket。
epoll是怎麼實現的呢?
簡單來說,epoll是基於文件描述符的callback函數來實現的,只有發生IO事件的socket會調用callback函數,然後加入epoll的Ready隊列。