信息安全系統設計基礎第十三週學習總結

時間統計

預計時間(10小時)

課本閱讀 6小時
整理筆記 3小時html

實際時間(12小時)

課本閱讀 7小時
整理筆記 5小時程序員

第十二章 併發編程

一、併發:邏輯控制流在時間上重疊 
二、併發程序:使用應用級併發的應用程序稱爲併發程序。 
三、三種基本的構造併發程序的方法:編程

(1)進程,用內核來調用和維護,有獨立的虛擬地址空間,顯式的進程間通訊機制。 
(2)I/O多路複用,應用程序在一個進程的上下文中顯式的調度控制流。邏輯流被模型化爲狀態機。 
(3)線程,運行在一個單一進程上下文中的邏輯流。由內核進行調度,共享同一個虛擬地址空間。安全

12.1 基於進程的併發編程

一、構造併發服務器的天然方法就是,在父進程中接受客戶端鏈接請求,而後建立一個新的子進程來爲每一個新客戶端提供服務。 
二、由於父子進程中的已鏈接描述符都指向同一個文件表表項,因此父進程關閉它的已鏈接描述符的拷貝是相當重要的,並且由此引發的存儲器泄露將最終消耗盡可用的存儲器,使系統崩潰。服務器

12.1.1 基於進程的併發服務器

基於進程的併發echo服務器的重點內容網絡

(1)須要一個SIGCHLD處理程序,來回收僵死子進程的資源。 
(2)父子進程必須關閉各自的connfd拷貝。對父進程尤其重要,以免存儲器泄露。 
(3)套接字的文件表表項中的引用計數,直到父子進程的connfd都關閉了,到客戶端的鏈接纔會終止。多線程

12.1.2 關於進程的優劣

注意:進程的模型:共享文件表,但不是共享用戶地址空間。 優勢:一個進程不可能不當心覆蓋兩一個進程的虛擬存儲器。 
缺點:獨立的地址空間使得進程共享狀態信息變得更加困難。進程控制和IPC的開銷很高。併發

Unix IPC是指全部容許進程和同一臺主機上其餘進程進行通訊的技術,包括管道、先進先出(FIFO)、系統V共享存儲器,以及系統V信號量。函數

12.2 基於I/O多路複用的併發編程

一、echo服務器必須響應兩個相互獨立的I/O時間: 
(1)網絡客戶端發起鏈接請求(2)用戶在鍵盤上鍵入命令行。 
二、I/O多路複用技術的基本思路:使用select函數,要求內核掛起進程,只有在一個或多個I/O事件發生後,纔將控制返回給應用程序。 
三、將描述符集合當作是n位位向量:b(n-1),……b1,b0 
每一個位bk對應於描述符k,當期僅當bk=1,描述符k才代表是描述符集合的一個元素。能夠作如下三件事: 
(1)分配它們;(2)將一個此種類型的變量賦值給另外一個變量;(3)用FDZERO、FDSET、FDCLR和FDISSET宏指令來修改和檢查它們。 
四、echo函數:未來自科幻段的每一行回送回去,直到客戶端關閉這個連接。學習

12.2.1 基於I/O多路複用的併發時間驅動服務器

一、狀態機就是一組狀態、輸入事件和轉移,轉移就是將狀態和輸入時間映射到狀態,自循環是同一輸入和輸出狀態之間的轉移。

12.2.2 I/O多路複用技術的優點

事件驅動器的設計優勢:

(1)比基於進程的設計給了程序員更多的對程序行爲的控制 
(2)運行在單一進程上下文中,所以,每一個邏輯流都能訪問該進程的所有地址空間,使得流之間共享數據變得很容易。 
(3)不須要進程上下文切換來調度新的流。 
缺點: 
(1)編碼複雜 
(2)不能充分利用多核處理器 
粒度:每一個邏輯流每一個時間片執行的指令數量。併發粒度就是讀一個完整的文本行所須要的指令數量。

12.3 基於線程的併發編程

一、線程:運行子啊進程上下文中的邏輯流。 
二、線程有本身的線程上下文,包括一個惟一的整數線程ID、棧、棧指針、程序計數器、通用目的寄存器和條件碼。全部運行在一個進程裏的線程共享該進程的整個虛擬地址空間。

12.3.1 線程執行模型

一、主線程:每一個進程開始生命週期時都是單一線程。 
對等線程:某一時刻,主線程建立的對等線程 
二、線程與進程的不一樣:

(1)線程的上下文切換要比進程的上下文切換快得多; 
(2)和一個進程相關的線程組成一個對等池,獨立於其餘線程建立的線程。 
(3)主線程和其餘線程的區別僅在於它老是進程中第一個運行的線程。

三、對等池的影響

(1)一個線程能夠殺死它的任何對等線程; 
(2)等待它的任意對等線程終止; 
(3)每一個對等線程都能讀寫相同的共享資源。

12.3.2 Posix線程

線程例程:線程的代碼和本地數據被封裝在一個線程例程中。每個線程例程都以一個通用指針做爲輸入,並返回一個通用指針。

12.3.3 建立線程

pthread create函數建立一個新的線程,並帶着一個輸入變量arg,在新線程的上下文中運行線程例程f。新線程能夠經過調用pthread _self函數來得到本身的線程ID。

12.3.4 終止線程

一個線程的終止方式: 
(1)當頂層的線程例程返回時,線程會隱式的終止; 
(2)經過調用pthread _exit函數,線程會顯示地終止。若是主線程調用pthread _exit,它會等待全部其餘對等線程終止,而後再終止主線程和整個進程。

12.3.5 回收已終止線程的資源

pthread _join函數會阻塞,直到線程tid終止,回收已終止線程佔用的全部存儲器資源。pthread _join函數只能等待一個指定的線程終止。

12.3.6 分離線程

一、在任何一個時間點上,線程是可結合的或者是分離的。一個可結合的線程可以被其餘線程收回其資源和殺死;一個可分離的線程是不能被其餘線程回收或殺死的。它的存儲器資源在它終止時有系統自動釋放。 
二、默認狀況下,線程被建立成可結合的,爲了不存儲器漏洞,每一個可集合的線程都應該要麼被其餘進程顯式的回收,要麼經過調用pthread _detach函數被分離。

12.3.7 初始化線程

pthread _once函數容許初始化與線程例程相關的狀態。 
once _control變量是一個全局或者靜態變量,老是被初始化爲PTHREAD _ONCE _INIT.

12.3.8 一個基於線程的併發服務器

對等線程的賦值語句和主線程的accept語句之間引入了競爭。

12.4 多線程程序中的變量共享

12.4.1 線程存儲器模型

一、每一個線程和其餘線程一塊兒共享進程上下文的剩餘部分。包括整個用戶虛擬地址空間,是由只讀文本、讀/寫數據、堆以及全部的共享庫代碼和數據區域組成的。線程也共享一樣的打開文件的集合。 二、任何線程均可以訪問共享虛擬存儲器的任意位置。寄存器是從不共享的,而虛擬存儲器老是共享的。

12.4.2 將變量映射到存儲器

一、全局變量:虛擬存儲器的讀/寫區域只會包含每一個全局變量的一個實例。 
二、本地自動變量:定義在函數內部但沒有static屬性的變量。 
三、本地靜態變量:定義在函數內部並有static屬性的變量。

12.4.3 共享變量

變量v是共享的,當且僅當它的一個實例被一個以上的線程引用。

12.5 用信號量同步線程

一、共享變量引入了同步錯誤的可能性。 
二、線程i的循環代碼分解爲五部分:

Hi:在循環頭部的指令塊 
Li:加載共享變量cnt到寄存器%eax的指令,%eax表示線程i中的寄存器%eax的值 
Ui:更新(增長)%eax的指令 
Si:將%eaxi的更新值存回到共享變量cnt的指令
Ti:循環尾部的指令塊。

12.5.1 進度圖

一、進度圖將指令執行模式化爲從一種狀態到另外一種狀態的轉換。轉換被表示爲一條從一點到相鄰點的有向邊。合法的轉換是向右或者向上。 
二、臨界區:對於線程i,操做共享變量cnt內容的指令構成了一個臨界區。 
三、互斥的訪問:確保每一個線程在執行它的臨界區中的指令時,擁有對共享變量的互斥的訪問。 
四、安全軌跡線:繞開不安全區的軌跡線 
不安全軌跡線:接觸到任何不安全區的軌跡線就叫作不安全軌跡線 
五、任何安全軌跡線都能正確的更新共享計數器。

12.5.2 信號量

一、當有多個線程在等待同一個信號量時,你不能預測V操做要重啓哪個線程。 
二、信號量不變性:一個正在運行的程序毫不能進入這樣一種狀態,也就是一個正確初始化了的信號量有一個負值。

12.5.3 使用信號量來實現互斥

一、二元信號量:將每一個共享變量與一個信號量s聯繫起來,而後用P(S)和V(s)操做將這種臨界區包圍起來,這種方式來保護共享變量的信號量。 
二、互斥鎖:以提供互斥爲目的的二元信號量 
加鎖:一個互斥鎖上執行P操做稱爲對互斥鎖加鎖,執行V操做稱爲對互斥鎖解鎖。對一個互斥鎖加了鎖但尚未解鎖的線程稱爲佔用了這個互斥鎖。 
計數信號量:一個唄用做一組可用資源的計數器的信號量

12.5.4 利用信號量來調度共享資源

一、信號量的做用:(1)提供互斥(2)調度對共享資源的訪問 二、生產者—消費者問題:生產者產生項目並把他們插入到一個有限的緩衝區中,消費者從緩衝區中取出這些項目,而後消費它們。 
三、讀者—寫者問題: 
(1)讀者優先,要求不讓讀者等待,除非已經把使用對象的權限賦予了一個寫者。 
(2)寫者優先,要求一旦一個寫者準備好能夠寫,它就會盡量地完成它的寫操做。 
(3)飢餓就是一個線程無限期地阻塞,沒法進展。

12.6 使用線程提升並行性

寫順序程序只有一條邏輯流,寫併發程序有多條併發流,並行程序是一個運行在多個處理器上的併發程序。並行程序的集合是併發程序集合的真子集。

12.7 其餘併發問題

12.7.1 線程安全

一、線程安全:當且僅當被多個併發線程反覆地調用時,它會一直產生正確的結果。 
線程不安全:若是一個函數不是線程安全的,就是線程不安全的。 
二、線程不安全的類: 
(1)不保護共享變量的函數 
(2)保持跨越多個調用的狀態的函數。 
(3)返回指向靜態變量的指針的函數。解決辦法:重寫函數和加鎖拷貝。
(4)調用線程不安全函數的函數。

12.7.2 可重入性

一、可重入函數:當它們被多個線程調用時,不會引用任何共享數據。可重入函數是線程安全函數的一個真子集 。 
二、關鍵思想是咱們用一個調用者傳遞進來的指針取代了靜態的next變量。 
三、顯式可重入:沒有指針,沒有引用靜態或全局變量 
隱式可重入:容許它們傳遞指針 
四、可重入性即便調用者也是被調用者的屬性,並不僅是被調用者單獨的屬性。

12.7.3 在線程化的程序中使用已存在的庫函數

12.7.4 競爭

一、競爭:當一個程序的正確性依賴於一個線程要在另外一個線程到達y點以前到達它的控制流中的x點時,就會發生競爭。 
二、線程化的程序必須對任何可行的軌跡線都正確工做。

12.7.5 死鎖

一、死鎖:一組線程被阻塞了,等待一個永遠也不會爲真的條件。 
二、程序員使用P和V操做不當,以致於兩個信號量的禁止區域重疊。 
三、重疊的禁止區域引發了一組稱爲死鎖區域的狀態。 
四、死鎖是不可預測的。

參考資料

一、教材:第十二章 二、課程資料:https://www.shiyanlou.com/courses/413 實驗樓實驗 三、學習指導:http://group.cnblogs.com/topic/73069.html

相關文章
相關標籤/搜索