目錄:
1.進程/線程/協程
2.多進程 多線程
3.進程狀態的切換
4.進程調度算法
5.進程同步
6.進程間的通信
進程/線程/協程:
進程是資源分配的基本單位。
進程控制塊(Process Control Block,PCB)描述進程的基本信息和運行狀態,進程的創建和撤銷都是由PCB來操作。
線程是獨立調度的基本單位。由(程序計數器,堆棧,和一組寄存器以及一個標識符組成)
協程又稱(微線程)是計算機程序的一類組件,推廣了協作式多任務的子程序,允許執行被掛起與被恢復。
一個進程可以有多個線程,共享進程資源。
進程與線程的區別:
- 擁有資源
- 進程是資源分配的基本單元,但是線程不擁有資源,線程可以訪問所屬進程的資源
- 調度
- 線程是獨立調度的基本單位,在同一進程中,線程的切換不會引起進程的切換,從一個進程中的線程切換到另一個進程中的線程時,會引起進程切換
- 系統開銷
- 創建或撤銷進程時,系統都要爲之分配或回收資源,如內存空間、I/O設備等,所付出的開銷遠大於創建或撤銷線程時的開銷。
- 通信方面
- 線程間可以通過直接讀寫同一進程中的數據進行通信,進程通信需要藉助IPC
協程的優勢:
- 協程最大的優勢就是協程有極高的執行效率,因爲子程序的切換不是進程的切換,而是程序自身控制,因此,沒有線程切換的開銷,和多線程相比,線程數量越多,協程顯現的優勢越大。
- 與多線程相比協程不需要鎖機制,因爲只有一個線程,也不會存在衝突的情況,控制共享資源時不需要加鎖,只需要判斷狀態就好了,所以執行效率要比線程高的很多。
協程如何利用多核cpu:多進程+協程。既充分利用多核,又充分發揮協程的高效率,可能獲得極高的性能。
多線程和多進程:
區別:
數據共享同步
- 多進程:數據是分開的:共享複雜,需要IPC;同步簡單
- 多線程:多線程共享進程數據簡單,同步複雜
內存CPU
- 多進程:佔用內存多,切換複雜,CPU利用率低
- 多線程:佔用內存少,切換簡單,CPU利用率高
創建銷燬切換:
1:多進程:複雜,速度慢。
2:所線程:簡單,速度快
編程調試:
1:.多進程:編程簡單調試簡單
2:多線程:編程複雜,調試複雜
可靠性:
1:多進程:進程間通信互不影響
2:多線程:一個線程掛掉將導致整個進程掛掉
優缺點:
多進程:
- 優點:內存隔離,單個進程的異常不會導致其他進程的奔潰,方便調試。
- 缺點:進程間的操作開銷比線程大
- 適合使用場合:目標的子功能之間的交互少
多線程:
1 優點:提高了系統的並行性,開銷小,對cup的利用率高
2 缺點:沒有內存隔離,單個線程的奔潰會導致整個應用程序的奔潰
3 使用場合:存在大量的IO,網絡等耗時操作。
4 在python中的缺點:Python中有全局解釋器鎖(GIL)的限制;並不是同一時刻,當線程的數目增多時需要進行切換,也會導致程序的整體性能下降。
Python的GIL(全局解釋器鎖)
- GIL本質是一個互斥鎖,可以防止多個線程同時執行python代碼。他是一個只由線程保持的鎖,當一個代碼在執行前必須獲取GIL鎖。優點在於,當它被鎖定時沒有別的線程可以同時運行代碼,一定程度上避免了線程間的衝突。
進程狀態的切換:
1.進程的三種狀態:
運行態:指該進程正在被CPU調度運行。
就緒態:指該進程滿足被cpu調度的所有條件但是並沒有被調度執行。
阻塞態:指該進程正在等待某事件的發生之後纔可以繼續被cpu調度運行。
- 三種狀態之間的切換;
- 就緒->運行 :當操作系統的調度程序從就緒態的鏈表中調度一個進程時,該進程的進程狀態就會被切換運行,與此同時cpu即開始進入運行狀態
- 運行->就緒:當一個正在運行的進程的時間片到達時,cpu必須調度下一個進程,此時處於運行狀態的進程被切換到就緒態,並重新進入操作系統的就緒態的進程鏈表。
- 運行->阻塞:當cpu正在運行一個進程時,該進程此時需要等待一個進程的完成才能繼續運行,這時操作系統就會將該進程狀態切換位阻塞狀態,知道進程所需要的等待條件完成
- 阻塞->就緒:進程從運行態直接切換爲阻塞態,當進程所需要的時間完成後,操作系統不會直接將該進程的狀態切換爲運行態,而是將該進程狀態切換爲就緒態,等待cpu的調度。
- Linux操作系統的進程狀態:
- R運行狀態:並不意味着進程一定是運行狀態,也可能是在運行隊列中。
- S睡眠狀態:進程在等待事件完成
- D磁盤睡眠狀態:不可終端睡眠(深度睡眠,不可被喚醒,通常發生在磁盤的寫入)
- T停止狀態:可以通過發送SIFSTOP信號給進程來停止進程,可以發送SIGCONT信號讓進程繼續運行
- X死亡狀態:該進程是返回狀態,在任務列表中看不到
- Z殭屍狀態:子進程退出,父進程還在運行,但是父進程沒有讀到子進程的退出狀態,子進程成爲殭屍狀態
- T追蹤停止狀態
- 不得不說的殭屍進程與孤兒進程
進程調度算法:
不同環境的調度算法目標不同,因此需要針對不同環境來討論調度算法
- 批處理系統
- 先來先服務:first-come first-serverd(FCFS)
- 非搶佔式調度算法,按照請求順序進行調度
- 有利於長作業,不利於短作業,短作業必須一直等待前面的長作業執行完畢才能執行,而長作業又需要執行很長事件,造成了短左右等待的時間過長
- 短作業優先shortest job first(SJF)
- 非搶佔式的調度算法,短作業優先的調度算法是從後備隊列中選擇一個或若干個估計運行時間最短的作業,將他們調入內存運行。而短作業優先是從就緒隊列中選出一個估計運行時間最短的進程,將處理及分配給它,使它立即執行並一直執行到完成。,。
- 短作業優先算法的缺點
- 不利於長作業,長作業的週期會明顯增加
- 沒有考慮作業的緊迫性,不能保證緊迫作業及時得到處理
- 最短剩餘時間優先:
- 最短優先爲搶佔式,按所有進程中剩餘時間最短的進行調度,當新的作業到達時,qi整個運行時間與黨當前進程的剩餘時間比較,誰短誰先。
- 先來先服務:first-come first-serverd(FCFS)
- 交互系統:
交互系統有大量的用戶交互操作,在該系統中調度算法的目標是快速地進行響應
-
- .時間片輪轉:
- 將所有就需進程按FCFS(先來先服務)的原則排成一個隊列,每次調度時,把cpu時間分配給隊首進程,該進程可以執行一個時間片。當時間片用完時,計時器會中斷,調度進程便停止該進程的執行,並將它送往就緒隊列的末尾,同時繼續把cpu時間分配給隊首的進程。
- 時間片輪轉算法的效率和時間片的大小有很大關係
- 時間太短會使進程切換太頻繁,在進程切換上會花費時間,時間太長,實時性就不能得到保障。
- 優先級調度:
- 爲每個進程分配一個優先級,按優先級進行調度。
- 爲了防止低的優先級的進程永遠得不到調度,可以隨着時間的推移增加等待進程的優先級
- 多級反饋隊列調度算法
- 多級隊列是爲這種需要連續執行多個時間片的進程考慮,它設置了多個隊列,可以分爲優先級不同且大小不同的隊列,最短的優先級最高,當一個進程進入一個隊列中如果在此隊列沒有執行完畢將會按FCFS來進入下一個隊列中以此類推,最上面的優先權最高,因此只有上一個隊列中沒有進程在排隊,才能調度當前隊列上的進程,(可以看出多級反饋隊列是時間片輪轉,和優先級調度的結合)
- .時間片輪轉:
進程同步
1. 臨界區
對臨界資源進行訪問的那段代碼稱爲臨界區
2 同步互斥
同步:多個進程因爲合作產生的直接制約關係,使得進程有一定的先後順序
互斥:多個進程在同一時刻只有一個進程能進入臨界區
3 信號量
信號量是一整個整型變量,可以對其執行down和up操作,也就是常見的p,v操作。
Down:如果信號量大於0,執行-1操作,如果信號量等於0,進程睡眠,等待信號量大於0
Up:對信號量執行+1操作,喚醒睡眠進程讓其完成down操作
4 管程
使用信號量機制實現的生產者消費者問題需要客戶端代碼做很多控制,而管程把控制代碼的代碼獨立出來,不僅不容易出錯也 使得客戶端代碼調用更容易
進程間的通信
- 管道/匿名管道(pipe)
- 管道是通過調用pipe函數創建,管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有血緣關係的進程間使用。進程的血緣關係通常是指父子進程關係。
- 數據的讀出和寫入:一個進程向管道中寫的內容被管道另一端的進程讀出。寫入的內容每次都添加在管道緩衝區的末尾,並且每次都是從緩衝區的頭部讀出數據。當緩衝區空或者寫滿時,有一定的規則控制相應的讀寫進程進入緩衝隊列,讓緩衝區有位置時,將喚醒等待隊列中的進程。
- 單獨構成一種獨立的文件系統,存在內存中
- 管道的實質:實質是一個循環隊列,進程以先進先出的方式從緩衝區存取數據,管道一端的進程順序的將數據寫入緩衝區,另一端的進程則順序的讀出數據。一個數據只能被讀一次,讀出來以後緩衝區就不復存在了
- 管道的侷限
- 只支持單向數據流
- 只能用於具有血緣關係的進程之間
- 管道的緩衝區時有限的(管道存在與內存中,在管道創建時,爲緩衝區分配一個頁面的大小)
- 管道所傳送的是無格式的字節流,所以要求管道的讀寫操作必須事先約定好數據的格式
- 有名管道(FIFO)
- 有名管道是爲了克服匿名管道只能同於血緣關係進程間的通信,有名管道不同於匿名管道之處在於它提供了一個路徑名與之關聯
- 有名管道嚴格遵循先進先出,對匿名管道及有名管道的讀總是從開始處返回數據,對他們的寫則是把數據添加到末尾。有名管道的名字存在於文件系統中,內容存放在內存中。
- 匿名管道和有名管道總結
- 管道是特殊的文件類型,在滿足先入先出的原則條件下可以進行讀寫,但不能進行定位讀寫
- 匿名管道是單向的,只能在有親緣關係的進程間通信;有名管道以磁盤文件的方式存在,可以實現本機任意兩個進程通信
- 無名管道阻塞問題:無名管道無需顯示打開,創建時直接返回文件描述符,在讀寫時需要確定對方的存在,否則將退出。如果當前進程向無名管道的一端寫數據,必須確定另一端有某一進程。如果寫入無名管道的數據超過最大值,寫操作將阻塞,如果管道沒有數據,讀操作將阻塞,如果管道發現另一端斷開,將自動退出
- 有名管道的阻塞問題:有名管道在打開時需要確定對方的存在,否則及將阻塞。即以讀方式打開某管道,再此之前必須一個進程以寫方式打開管道,否則阻塞,此外可以用讀寫模式打開有名管道,即當前進程讀,當前進程寫不會阻塞。
- 消息隊列:
- 消息隊列提供了一種從一個進程向另一個進程發送一個進程塊的方法。每個數據快都被認爲含有一個類型,接受進程可以獨立的接受含有不同數據類型的數據結構。通過發送消息來避免命名管道的同步和阻塞問題,消息隊列與命名管道一樣每個數據塊都有最大的長度限制。
- 消息隊列與命名管道的比較:
- 消息隊列也可以獨立發送和接收進程而存在,從而消除在同步命名管道的打開和關閉時可能產生的困難。
- 同時通過發送消息可以避免命名管道的同步和阻塞問題,不需要由進程自己來提供方法。
- 接收程序可以通過消息類型有選擇的接收數據,而不是向命名管道只能默認的接收。
- 信號量(本質就是一個計數器,用於爲多個進程提供對共享數據的訪問):
- 看信號量之前首先要搞清楚一下幾個概念:
- 進程互斥:兩個或兩個以上的進程不能同時進入同一組共享資源的臨界區,否則可能發生與時間有關的錯誤,也就是說一個進程在訪問臨界資源,另一個進程必須等待。
- 進程同步:在多道程序環境下,進程是併發執行的,不同進程之間存在着不同的相互制約關係
- 臨界資源:系統中某些資源只允許一個進程使用。
- 臨界區:再進程中涉及到互斥資源的臨界區
- 原子性:不可被中斷的操作。
什麼是信號量:爲了防止出現多個程序同時訪問一個共享資源而引發的一系列問題,我們需要一種方法,他可以通過生產並使用令牌來授權,在任一時刻只能有一個執行線程訪問代碼的臨界區域。而信號量可以提供這種訪問機制,讓一個臨界區同一時間只有一個線程訪問它,也就是說信號量是用來協調進程對共享資源的訪問。
當請求一個使用信號量來表示的資源時,進程需要先讀取信號量的值來判斷資源是否可用:-
信號量>0:表示資源可用於請求
-
信號量=0:無資源可用,進程會進入睡眠狀態直至資源可用
-
當信號量不再使用一個信號量控制共享資源時,信號量+1,對信號量的值進行增加操作均爲原子操作。而在信號量的創建及初始化上,不能保證操作均爲原子性。
-
信號量的生命週期:信號量的生命週期與消息隊列是一樣的不隨進程的結束而結束,而是隨內核的。
-
信號量的工作原理:
-
P(sv):如果sv的值大於0,就對其減1;如果它的值爲零,就掛起該進程的執行。
-
V(sv):如果有其他進程因等待sv而被掛起,就讓他恢復運行;如果沒有進程因等待sv而掛起,就給他加1
-
舉例說明:兩個進程共享信號量sv,一旦其中一個進程執行了P(sv)操作,它將得到信號量,並可以進入臨界區,使sv減1.而第二個進程將被阻止進入臨界區,因爲當他試圖執行P(sv)時,sv爲0,它會被掛起以等待第一個進程離開臨界區執行V(sv)時釋放信號量,這時第二個進程可以恢復執行。
-
二元信號量:時最簡單的一種鎖,它只有兩種狀態(佔有與非佔有)。它適合只能被唯一一個線程訪問資源。當二元信號量處於非佔用狀態時,第一個試圖獲取該二元信號量的線程會獲得該鎖,並將二元信號量置爲佔用狀態,其他所有試圖獲取該二元信號量的進程將會等待,直到該鎖被釋放。
-
- 看信號量之前首先要搞清楚一下幾個概念:
-
共享內存:
-
共享內存就是允許兩個不相關的進程訪問同一個邏輯內存。共享內存是在兩個正在運行的進程之間共享和傳遞數據的一種非常有效的方式。不同進程之間共享的內存通常安排爲同一段物理內存,進程可以將同一段共享內存連接到他們自己的地址空間中,所有進程可以訪問共享內存中地址。而如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。
-
因爲數據不需要在進程之間複製,所以只最快的一種IPC 。使用共享內存要注意的是多個進程之間對一個給定存儲區訪問的互斥。若一個進程正在向共享內存區寫入數據,則在其他做完這一步操作前,別的進程不應當區讀,寫這些數據。需要使用信號量用來同步對共享存儲的訪問。多個進程可以及那個同一個文件映射到它們的地址空間從而實現共享內存。
-
-
套接字:
-
與其他進程不同的是,它可用於不同機器間的進程通信。socket是套接字的一種通信機制,憑藉這種機制,客戶/服務器系統的開發工作既可以在本地單機上進行,也可以跨網絡進行,也就是說它可以讓不同一臺計算機但通過網絡連接計算機上的進程進行通信。也因爲這樣套接字明確地將客戶端和服務端分開來。
-
套接字的三種屬性:套接字的域,套接字類型,套接字協議。
-
套接字域:指定套接字通信中使用的網絡介質。做常見的就是Internet網絡
-
套接字類型:Internet提供兩種通信機制:流和數據報
-
套接字協議:只要底層的傳輸機制允許不止一個協議來提供要求的套接字類型,可以爲套接字選擇一個特定的協議。通常只需要默認值。
-
-