1. 程式人生 > >並行 並發

並行 並發

應用 alt 兩個 存在 ike 管理 經理 kill 作業

進程 Process

進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體。

狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being executed)。 廣義定義:進程是一個具有一定獨立功能的程序關於某個數據集合的一次運行活動。它是操作系統動態執行的基本單元,在傳統的操作系統中,進程既是基本的分配單元,也是基本的執行單元。

進程的特征

動態性:進程的實質是程序在多道程序系統中的一次執行過程,進程是動態產生,動態消亡的。
並發性:任何進程都可以同其他進程一起並發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
異步性:由於進程間的相互制約,使進程具有執行的間斷性,即進程按各自獨立的、
不可預知的速度向前推進
結構特征:進程由程序、數據和進程控制塊三部分組成。 多個不同的進程可以包含相同的程序:一個程序在不同的數據集裏就構成不同的進程,

能得到不同的結果;但是執行過程中,程序不能發生改變。

進程的調度

要想多個進程交替運行,操作系統必須對這些進程進行調度,這個調度也不是隨即進行的,而是需要遵循一定的法則,由此就有了進程的調度算法。

先來先服務算法:

先來先服務(FCFS)調度算法是一種最簡單的調度算法,該算法既可用於作業調度,也可用於進程調度。
FCFS算法比較有利於長作業(進程),而不利於短作業(進程)。
由此可知,本算法適合於CPU繁忙型作業,而不利於I/O繁忙型的作業(進程)。

短作業優先算法

短作業(進程)優先調度算法(SJ/PF)是指對短作業或短進程優先調度的算法,
該算法既可用於作業調度,也可用於進程調度。
但其對長作業不利;不能保證緊迫性作業(進程)被及時處理;作業的長短只是被估算出來的。

時間輪片算法

技術分享圖片
時間片輪轉(Round Robin,RR)法的基本思路是讓每個進程在就緒隊列中的等待時間與享受服務的時間成比例。在時間片輪轉法中,需要將CPU的處理時間分成固定大小的時間片,例如,幾十毫秒至幾百毫秒。如果一個進程在被調度選中之後用完了系統規定的時間片,但又未完成要求的任務,則它自行釋放自己所占有的CPU而排到就緒隊列的末尾,等待下一次調度。同時,進程調度程序又去調度當前就緒隊列中的第一個進程。
顯然,輪轉法只能用來調度分配一些可以搶占的資源。這些可以搶占的資源可以隨時被剝奪,而且可以將它們再分配給別的進程。CPU是可搶占資源的一種。但打印機等資源是不可搶占的。由於作業調度是對除了CPU之外的所有系統硬件資源的分配,其中包含有不可搶占資源,所以作業調度不使用輪轉法。
在輪轉法中,時間片長度的選取非常重要。首先,時間片長度的選擇會直接影響到系統的開銷和響應時間。如果時間片長度過短,則調度程序搶占處理機的次數增多。這將使進程上下文切換次數也大大增加,從而加重系統開銷。反過來,如果時間片長度選擇過長,例如,一個時間片能保證就緒隊列中所需執行時間最長的進程能執行完畢,則輪轉法變成了先來先服務法。時間片長度的選擇是根據系統對響應時間的要求和就緒隊列中所允許最大的進程數來確定的。
在輪轉法中,加入到就緒隊列的進程有3種情況:
一種是分給它的時間片用完,但進程還未完成,回到就緒隊列的末尾等待下次調度去繼續執行。
另一種情況是分給該進程的時間片並未用完,只是因為請求I
/O或由於進程的互斥與同步關系而被阻塞。當阻塞解除之後再回到就緒隊列。 第三種情況就是新創建進程進入就緒隊列。 如果對這些進程區別對待,給予不同的優先級和時間片從直觀上看,可以進一步改善系統服務質量和效率。例如,我們可把就緒隊列按照進程到達就緒隊列的類型和進程被阻塞時的阻塞原因分成不同的就緒隊列,每個隊列按FCFS原則排列,各隊列之間的進程享有不同的優先級,但同一隊列內優先級相同。這樣,當一個進程在執行完它的時間片之後,或從睡眠中被喚醒以及被創建之後,將進入不同的就緒隊列。
時間輪片算法

多級反饋隊列

前面介紹的各種用作進程調度的算法都有一定的局限性。如短進程優先的調度算法,僅照顧了短進程而忽略了長進程,而且如果並未指明進程的長度,則短進程優先和基於進程長度的搶占式調度算法都將無法使用。
而多級反饋隊列調度算法則不必事先知道各種進程所需的執行時間,而且還可以滿足各種類型進程的需要,因而它是目前被公認的一種較好的進程調度算法。在采用多級反饋隊列調度算法的系統中,調度算法的實施過程如下所述。
(1) 應設置多個就緒隊列,並為各個隊列賦予不同的優先級。第一個隊列的優先級最高,第二個隊列次之,其余各隊列的優先權逐個降低。該算法賦予各個隊列中進程執行時間片的大小也各不相同,在優先權愈高的隊列中,為每個進程所規定的執行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。
(2) 當一個新進程進入內存後,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度。當輪到該進程執行時,如它能在該時間片內完成,便可準備撤離系統;如果它在一個時間片結束時尚未完成,調度程序便將該進程轉入第二隊列的末尾,再同樣地按FCFS原則等待調度執行;如果它在第二隊列中運行一個時間片後仍未完成,再依次將它放入第三隊列,……,如此下去,當一個長作業(進程)從第一隊列依次降到第n隊列後,在第n 隊列便采取按時間片輪轉的方式運行。

(3) 僅當第一隊列空閑時,調度程序才調度第二隊列中的進程運行;僅當第1~(i-1)隊列均空時,才會調度第i隊列中的進程運行。如果處理機正在第i隊列中為某進程服務時,又有新進程進入優先權較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進程將搶占正在運行進程的處理機,即由調度程序把正在運行的進程放回到第i隊列的末尾,把處理機分配給新到的高優先權進程。

多級反饋隊列

技術分享圖片

同步異步阻塞與非阻塞

技術分享圖片

就緒(Ready)狀態

  當進程已分配到除CPU以外的所有必要的資源,只要獲得處理機便可立即執行,這時的進程狀態稱為就緒狀態。

執行/運行(Running)狀態

  當進程已獲得處理機,其程序正在處理機上執行,此時的進程狀態稱為執行狀態。

阻塞(Blocked)狀態

  正在執行的進程,由於等待某個事件發生而無法執行時,便放棄處理機而處於阻塞狀態。引起進程阻塞的事件可有多種,例如,等待I/O完成、申請緩沖區不能滿足、等待信件(信號)等。

同步和異步

所謂同步就是一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後,依賴的任務才能算完成,這是一種可靠的任務序列。要麽成功都成功,失敗都失敗,兩個任務的狀態可以保持一致。

  所謂異步是不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什麽工作,依賴的任務也立即執行,只要自己完成了整個任務就算完成了。至於被依賴的任務最終是否真正完成,依賴它的任務無法確定,所以它是不可靠的任務序列

技術分享圖片
比如我去銀行辦理業務,可能會有兩種方式:
第一種 :選擇排隊等候;
第二種 :選擇取一個小紙條上面有我的號碼,等到排到我這一號時由櫃臺的人通知我輪到我去辦理業務了;

第一種:前者(排隊等候)就是同步等待消息通知,也就是我要一直在等待銀行辦理業務情況;

第二種:後者(等待別人通知)就是異步等待消息通知。在異步消息處理中,等待消息通知者(在這個例子中就是等待辦理業務的人)往往註冊一個回調機制,在所等待的事件被觸發時由觸發機制(在這裏是櫃臺的人)通過某種機制(在這裏是寫在小紙條上的號碼,喊號)找到等待該事件的人。
例子

阻塞與非阻塞

阻塞和非阻塞這兩個概念與程序(線程)等待消息通知(無所謂同步或者異步)時的狀態有關。也就是說阻塞與非阻塞主要是程序(線程)等待消息通知時的狀態角度來說的

技術分享圖片
繼續上面的那個例子,不論是排隊還是使用號碼等待通知,如果在這個等待的過程中,等待者除了等待消息通知之外不能做其它的事情,那麽該機制就是阻塞的,表現在程序中,也就是該程序一直阻塞在該函數調用處不能繼續往下執行。
相反,有的人喜歡在銀行辦理這些業務的時候一邊打打電話發發短信一邊等待,這樣的狀態就是非阻塞的,因為他(等待者)沒有阻塞在這個消息通知上,而是一邊做自己的事情一邊等待。

註意:同步非阻塞形式實際上是效率低下的,想象一下你一邊打著電話一邊還需要擡頭看到底隊伍排到你了沒有。如果把打電話和觀察排隊的位置看成是程序的兩個操作的話,這個程序需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的;而異步非阻塞形式卻沒有這樣的問題,因為打電話是你(等待者)的事情,而通知你則是櫃臺(消息觸發機制)的事情,程序沒有在兩種不同的操作中來回切換。
例子

同步/異步與阻塞/非阻塞

  1. 同步阻塞形式

  效率最低。拿上面的例子來說,就是你專心排隊,什麽別的事都不做。

  1. 異步阻塞形式

  如果在銀行等待辦理業務的人采用的是異步的方式去等待消息被觸發(通知),也就是領了一張小紙條,假如在這段時間裏他不能離開銀行做其它的事情,那麽很顯然,這個人被阻塞在了這個等待的操作上面;

  異步操作是可以被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。

  1. 同步非阻塞形式

  實際上是效率低下的。

  想象一下你一邊打著電話一邊還需要擡頭看到底隊伍排到你了沒有,如果把打電話和觀察排隊的位置看成是程序的兩個操作的話,這個程序需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的。

  1. 異步非阻塞形式

  效率更高,

  因為打電話是你(等待者)的事情,而通知你則是櫃臺(消息觸發機制)的事情,程序沒有在兩種不同的操作中來回切換

  比如說,這個人突然發覺自己煙癮犯了,需要出去抽根煙,於是他告訴大堂經理說,排到我這個號碼的時候麻煩到外面通知我一下,那麽他就沒有被阻塞在這個等待的操作上面,自然這個就是異步+非阻塞的方式了。

  

很多人會把同步和阻塞混淆,是因為很多時候同步操作會以阻塞的形式表現出來,同樣的,很多人也會把異步和非阻塞混淆,因為異步操作一般都不會在真正的IO操作處被阻塞

進程的創建

但凡是硬件,都需要有操作系統去管理,只要有操作系統,就有進程的概念,就需要有創建進程的方式,一些操作系統只為一個應用程序設計,比如微波爐中的控制器,一旦啟動微波爐,所有的進程都已經存在。

  而對於通用系統(跑很多應用程序),需要有系統運行過程中創建或撤銷進程的能力,主要分為4中形式創建新的進程:

  1. 系統初始化(查看進程linux中用ps命令,windows中用任務管理器,前臺進程負責與用戶交互,後臺運行的進程與用戶無關,運行在後臺並且只在需要時才喚醒的進程,稱為守護進程,如電子郵件、web頁面、新聞、打印)

  2. 一個進程在運行過程中開啟了子進程(如nginx開啟多進程,os.fork,subprocess.Popen等)

  3. 用戶的交互式請求,而創建一個新進程(如用戶雙擊暴風影音)

  4. 一個批處理作業的初始化(只在大型機的批處理系統中應用)

  無論哪一種,新進程的創建都是由一個已經存在的進程執行了一個用於創建進程的系統調用而創建的。  

技術分享圖片
1. 在UNIX中該系統調用是:fork,fork會創建一個與父進程一模一樣的副本,二者有相同的存儲映像、同樣的環境字符串和同樣的打開文件(在shell解釋器進程中,執行一個命令就會創建一個子進程)

  2. 在windows中該系統調用是:CreateProcess,CreateProcess既處理進程的創建,也負責把正確的程序裝入新進程。

  關於創建子進程,UNIX和windows

  1.相同的是:進程創建後,父進程和子進程有各自不同的地址空間(多道技術要求物理層面實現進程之間內存的隔離),任何一個進程的在其地址空間中的修改都不會影響到另外一個進程。

  2.不同的是:在UNIX中,子進程的初始地址空間是父進程的一個副本,提示:子進程和父進程是可以有只讀的共享內存區的。但是對於windows系統來說,從一開始父進程與子進程的地址空間就是不同的。

創建進程
創建進程

進程的結束

  1. 正常退出(自願,如用戶點擊交互式頁面的叉號,或程序執行完畢調用發起系統調用正常退出,在linux中用exit,在windows中用ExitProcess)

  2. 出錯退出(自願,python a.py中a.py不存在)

  3. 嚴重錯誤(非自願,執行非法指令,如引用不存在的內存,1/0等,可以捕捉異常,try...except...)

  4. 被其他進程殺死(非自願,如kill -9)

---恢復內容結束---

並行 並發