上一篇部落格是複習作業系統程序篇的上篇,包括程序狀态、PCB、程序控制等——我的作業系統複習——程序(上),本篇博文是程序篇的下篇,開始複習程序同步、程序通信,以及重要的線程概念。
一、程序同步
什麼是同步?同步就是說一個任務要等另一個執行完畢才能繼續執行,而不是同時執行。我們都知道,程序有異步性,這種性質會導緻作業系統的混亂。程序同步,指的是程序之間的執行次序的管理,就是為了解決程序異步性的這種混亂。
(1)直接制約和間接制約。
程序之間有兩種制約關系。分别是直接制約和間接制約。直接制約指的是程序間的合作,即一個程序需要另一個程序的配合,否則會阻塞。如輸出緩沖區為空的時候,輸出程序就會阻塞,輸出程序依賴輸入程序不斷的輸入。間接制約指的是對于某種資源,同時隻能有一個程序占用,你用的時候,别人就不能用。
(2)同步機制應遵循的規則。
這是所有的同步機制所需要遵循的規則:
1)空閑讓進。資源空閑的時候,允許程序通路。
2)忙則等待。資源被占用的時候,程序必須等待。
3)有限等待。應保證程序有限時間能通路到資源,不能無限等待。
4)讓權等待。運作中的程序不能通路指定資源時,應釋放處理機。
二、PV操作
PV操作的鼎鼎大名,想必很多人都聽說過。它就是經典的實作最基本的程序同步機制的一對操作。為什麼叫PV操作呢?它是鼎鼎大名的計算機學家狄克斯特拉用荷蘭語定義的,在荷蘭文中,通過叫passeren,釋放叫vrijgeven。P操作又叫Wait(S),本質是使用資源,V操作又叫Sign(S),本質是釋放資源。PV操作都是原子操作,要麼全做,要麼全不做,并且PV操作是成對的。我們來詳細看看PV操作的原理,是怎麼實作程序同步的。PV操作跟信号量是分不開的,先看看什麼是信号量。
(1)什麼是信号量?
信号量是一種資料結構。包括整形信号量、記錄型信号量、AND型信号量和信号量集等。不同的信号量對應不同的資料結構,也對應不同的PV操作。信号量和操作它的PV操作構成了對
應的信号量機制,用來控制程序同步。
(2)整型信号量。
顧名思義,整形信号量的資料結構就是一個簡單的整形,一般用整形S來表示。其上的PV操作如下:
(這裡的程式代碼都是Pascal代碼)
wait(S): while S <= 0 do no-op;
s := s - 1
sinal(S): s := s + 1
如上,S代表的是資源數目。對于wait(S)操作,當資源數目小于等于0的時候,就一直等待。若有資源,就跳出循環,使用一個資源。
對于sinal(S)操作,每次執行都釋放一個資源。
(3)記錄型信号量。
這個信号量比整形信号量增加了一個辨別程序指針的屬性,指向所有等待的程序連結清單。
PV操作與整形信号量的差別在于,wait()時,若s<=0,那麼阻塞自身,放棄處理機。signal()後,判斷若s<=0,就喚醒一個程序。它的好處是當程序請求不到資源的時候,不會無限等待。
(4)AND型信号量。
AND型信号量是針對多個臨界資源而言的。即将程序運作中所需要的所有資源一次性配置設定給程序,程序運作完畢後釋放所有資源。相當于把程序所需的所有資源捆綁在一起了。做法就是在wait操作中增加一個AND條件:隻有當程序所需的所有資源處于空閑狀态時,程序才能繼續操作。
(5)信号量集。
信号量集指的是一次性對N個某類資源的請求處理。上面的AND型信号量指的是對多個不同類型資源的處理,而信号量集指的是對同類的多個資源的處理,也相當于AND型信号量的特殊情況。
(6)管程
由于程序對某一個資源進行操作的時候,都需要自帶一對PV操作,為了避免這種情況,把某個資源和程序對其進行的操作包裝起來,這樣的一個子產品稱為管程。它是作業系統中的一個資源管理子產品,供程序調用。可以看到,管程實作了面向對象的思想。
(7)條件變量
在上面的程序同步的實作中都有一個很嚴重的隐含問題,那就是,如果某個程序一直不釋放某個資源,其他程序就隻能無止休地等待。條件變量的意義在于,除了原本的資源空閑就讓進、處理完就釋放這樣的邏輯外,還有其他的條件。例如:資源空閑且XX條件,就讓進。處理完成或XX條件就釋放資源。這些額外的條件,就叫條件變量。
三、程序通信
上面的通過信号量進行的程序同步,其本質是一種低級的通信機制。程序之間無法大量交換資訊。那麼兩個程序之間想要實作大量的、頻繁的資訊交換,該怎麼做呢?這就是進階通信機制了。進階通信機制有三大類:
(1)共享存儲器系統。
存儲器即記憶體,共享存儲器,顧名思義,就是通信的兩個程序通過共享的一塊記憶體區域來通信,一個負責讀一個負責寫。而實際上面的信号量也是一種共享存儲器系統,隻不過程序間共享的是一個資料結構,并用PV操作對資料結構進行操作。
(2)消息傳遞系統。
程序間通過指定格式的消息進行通信。消息格式通常就是一個包含位址的頭和一個包含内容的body。這種格式也叫做協定。我們常見的網絡協定也是這種方式。消息傳遞系統分為直接通信方式和間接通信方式。直接通信方式即通信的程序雙方都知道對方的存在,并在消息頭中攜帶了自身和對方的位址資訊。間接通信方式即程序間的消息傳遞不是直接傳遞給對方,而是有一個中間實體暫存、并轉發,這樣避免了程序雙方接收、發送資料的速率不統一導緻的程序阻塞。
(3)管道通信。
管道是一種連接配接讀程序和寫程序的共享檔案——pipe檔案,其本質是固定大小的緩沖區,這個緩沖區将2個程序連接配接起來,這兩個程序對管道是互斥的通路,且寫程序寫入資料後便阻塞,直到讀程序取走所有資料才被喚醒繼續寫資料。這種一次性的讀操作和寫操作,雖然會導緻程序堵塞,但是在讀寫的過程中無須維護讀寫指針,效率非常高。
四、線程
線程是什麼?線程就為了使作業系統能夠有更好的并發而建立的,相當于隻擁有少量資源的程序——輕型程序。在這種多線程作業系統中,程序是擁有系統資源的基本機關,包含多個線程,為其提供資源,而程序本身不再作為可執行的實體,當程序執行的時候,實際上是其中的某個線程在執行。
(1)線程執行的本質。
了解線程就必須深入了解并發。并發的本質就是單處理機系統永遠都是線性執行任務的。而線程的本質就是将原本為實作程序的時間片劃分的更細,假設在某個單處理機作業系統中,時間片為20毫秒,即一個程序的單次執行時間為20毫秒,在這個程序内有50個線程在執行,那麼劃分後,平均每個線程的執行時間肯定小于0.4毫秒。不過對于大部分任務而言,這仍舊是足夠的。線程無非就是這樣。
(2)線程的類型和實作。
1)使用者級線程(User Level Thread)——ULT。
這種線程的實作非常簡單,對于處理器而言,它仍舊是在進行程序切換,并不知道有線程的存在。如果每個程序相當于一個車子,那每個線程都相當于一個司機,線程切換就是不斷在換司機。
那麼在程序内部如何分割出各種多線程的呢?程序中有一個函數集合,專門用來管理和控制線程的執行。這個函數集合被稱為運作時系統。程序執行時就是執行它的運作時系統,對其中的線程進行切換管理。線程的運作時資訊——線程控制塊TCB存放在各自的堆棧中,每次切換的時候,運作時系統就從線程的堆棧中取得對應的運作時資訊,設定CPU的寄存器中,之後便可以運作。值得注意的是,線程是不能直接調用系統資源的,線程需要系統資源時,需要由運作時系統來調用配置設定。
2)核心支援線程(KernelSupported Thread)——KST。
這種線程的建立、撤銷、切換就不是依賴程序,是直接像程序排程一樣由核心控制,由于線程基本不用有資源,是以這種排程也很快。核心支援線程的線程優先級通常比使用者級線程要高很多。
那麼核心支援線程如何實作的呢?建立一個程序時,系統為之配置設定一個任務資料區(Per Task Data Area),其中包含若幹線程控制塊TCB,這些TCB并非存放在程序資源記憶體中,而是儲存在CPU的寄存器中。然後進行跟PCB非常類似的由處理器切換控制。
3)組合方式,由輕型程序(Light weight process)——LWP實作。
核心支援多KST線程的建立,同時支援ULT線程的建立,這種支援是通過輕型程序LWP實作的。輕型程序LWP的本質就是一個KST程序,它的特點就是能夠讓ULT連接配接,當ULT連接配接它的時候,就相當于在調用KST,可以實作KST的所有功能。是以一般LWP都是用線程池來實作的。可以看到LWP的目的就是為了讓使用者級線程ULT直接能調用系統資源。
參考:《計算機作業系統(湯子瀛)》
/**
* ————————如果覺得本博文還行,别忘了推薦一下哦,謝謝!
* 作者:錢書康
* 歡迎轉載,請保留此段聲明。
* 出處:http://www.cnblogs.com/zrtqsk/
*/