進程控制塊PCB(Process Control Block)node
進程存在的標識,在Linux系統中是task_struct,task_struct在內核棧(Linux進程氛圍用戶棧和內核棧)的尾端分配。mysql
從低地址到高地址:程序員
進程是擁有資源的基本單位,進程的地址空間相互獨立;web
線程是獨立調度的基本單位,共享同一個進程內的資源(線程有本身的棧),減小了程序併發時所付出的時空開銷,而且能夠高效的共享數據,有效地利用多處理器和多核計算機,提升os的併發度。算法
一個進程異常退出不會引發另外的進程運行異常;可是線程若異常退出通常是會引發整個進程奔潰。sql
建立/撤銷/切換 進程的開銷遠大於線程的(建立線程比建立進程快10~100倍 UNPv2/P406)。數據庫
孤兒進程 —— 父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成爲孤兒進程。孤兒進程將被init進程(進程號爲1)所收養,並由init進程對它們完成狀態收集工做。安全
殭屍進程 —— 一個進程使用fork建立子進程,若是子進程退出,而父進程並無調用wait或waitpid獲取子進程的狀態信息,那麼子進程的進程描述符仍然保存在系統中。服務器
守護進程 —— 守護進程的父進程是init進程,由於它真正的父進程在fork出子進程後就先於子進程exit退出了,因此它是一個由init繼承的孤兒進程。不須要用戶輸入就能運行並且提供某種服務,不是對整個系統就是對某個用戶程序提供服務。常見的守護進程包括系統日誌進程syslogd、 web服務器httpd、郵件服務器sendmail和數據庫服務器mysqld等。網絡
最大進程數受如下3方面限制:
UNP 分了如下幾中形式的IPC:
進程間通訊方式:匿名管道,有名管道,消息隊列,共享內存,信號量,套接字,域套接字,信號
線程同步方式:互斥量,條件變量,讀寫鎖
半雙工的(即數據只能在一個方向上流動),具備固定的讀端和寫端;是一種特殊的文件(pipefs,掛載在內核中),有固定大小,只存在於內存中;
實現原理:
管道是由內核管理的一個緩衝區,被設計成爲環形的數據結構,以便管道能夠被循環利用。當管道中沒有信息的話,從管道中讀取的進程會等待,直到另外一端的進程放入信息。當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另外一端的進程取出信息。當兩個進程都終結的時候,管道也自動消失。
在 Linux 中,管道的實現藉助了文件系統的file結構和VFS的索引節點inode。經過將兩個file結構指向同一個臨時的VFS索引節點,而這個VFS索引節點又指向一個物理頁面而實現的。
內核會利用必定的機制同步對管道的訪問。
半雙工,可在無關進程使用;FIFO有路徑名與之相關聯,以一種特殊設備文件形式存在於文件系統中
實現原理:
Linux中設立了一個專門的特殊文件系統--管道文件,FIFO在文件系統中有對應的路徑。當一個進程以讀(r)的方式打開該文件,而另外一個進程以寫(w)的方式打開該文件,那麼內核就會在這兩個進程之間創建管道,雖然FIFO在VFS的目錄樹下可見,可是它並不對應disk上的文件。
本質上是一個先進先出的隊列數據結構,最先放入的數據被最早讀出來,從而保證信息交流的順序。FIFO只是借用了文件系統來爲管道命名。當刪除FIFO文件時,管道鏈接也隨之消失。當進程終止時,管道內的數據會被刪除。
共享內存是最快的:
一般往管道、FIFO或消息隊列寫入數據時,這些IPC須要將數據從進程複製到內核,一般總共須要複製4次,而共享內存則只拷貝2次數據;如圖:
用於通知接收進程,有某種事件發生。
信號是在軟件層次上對中斷機制的一種模擬,在原理上,一個進程收到一個信號與處理器收到一箇中斷請求能夠說是同樣的。信號是異步的,一個進程沒必要經過任何操做來等待信號的到達。
加鎖原語,排他性訪問共享數據,用於保護臨界區。可細分爲遞歸鎖/非遞歸鎖。
若是存在某個線程依然使用原先的程序
(即不嘗試得到mutex,而直接修改共享變量),互斥鎖不能阻止其修改。因此,互斥鎖機制須要程序員本身來寫出完善的程序來實現互斥鎖的功能(如下鎖 同樣)。
互斥鎖用於上鎖,條件變量用於等待,條件變量的使用是與互斥鎖共通使用的。
條件變量學名叫管程(monitor)【From muduo P40】。
讀寫鎖也叫作 共享-獨佔鎖,容許更高的併發度。
互斥量要麼是鎖住狀態,要麼是不加鎖狀態,並且一次只有一個線程對其加鎖。
讀寫鎖能夠有三種狀態:讀模式下加鎖狀態,寫模式下加鎖狀態,不加鎖狀態。一次只有一個線程能夠佔有寫模式的讀寫鎖,可是多個線程可用同時佔有讀模式的讀寫鎖。
讀寫鎖能夠經過使用互斥鎖和條件變量來實現。
在獲取鎖以前一直處於忙等(自旋)阻塞狀態;經常使用於
鎖被持有的時間短,且線程並不但願在從新調度上花費太多成本。當線程自旋等待鎖變爲可用時,CPU不能作其餘事情。
故而自旋鎖常做爲底層原語,用於實現其餘類型的鎖。
記錄鎖是讀寫鎖的一種擴展類型,可用於親緣關係或無親緣關係的進程之間共享某個文件的讀與寫。被鎖住的文件經過文件描述符進行訪問,執行上鎖的操做函數是fcntl,這種類型的鎖一般在內核中維護。
記錄鎖的功能是:一個進程正在讀或修改文件的某個部分時,能夠阻止其餘進程修改同一文件區,即其鎖定的是文件的一個區域或整個文件。
記錄鎖有兩種類型:共享讀鎖,獨佔寫鎖。基本規則是:多個進程在一個給定的字節上能夠有一把共享的讀鎖,但在一個給定字節上的寫鎖只能有一個進程獨用。即:若是在一個給定的字節上已經有一把讀或多把讀鎖,則不能在該字節上再加寫鎖;若是在一個字節上已經有一把獨佔性的寫鎖,則不能再對它加任何讀鎖。
處理死鎖的策略:
通常來講,打破循環使用資源最容易,即順序加減鎖
銀行家算法(死鎖避免算法)。在資源動態分配過程當中,防止系統進入不安全狀態,以免發生死鎖。
數據庫中會用到等待圖進行死鎖檢測
在Linux下,信號量和線程互斥鎖的實現都是經過futex系統調用。