天天看點

資訊安全系統設計基礎第十三周學習總結

并發程式設計

并發可以看做是一種作業系統在核心用來運作多個應用程式的機制,也可以應用程式中扮演重要角色

·通路慢速I/O裝置:交替執行I/O請求和其他有用工作來使用并發
·與人互動:和計算機互動的人同樣要求計算機有同時執行多個任務的能力
·推遲工作以降低延遲:推遲其他操作和并發的執行,利用并發來執行操作的延遲
·服務多個網絡用戶端:建立并發伺服器,為每個用戶端建立單獨的邏輯劉,避免獨占
·在多核機器上進行并行計算:被劃分成并行流的應用程式在多核機器上運作的比在單核快
           

構造并發程式的方法

·程序
·I/O多路複用
·線程
           

12.1 基于程序的并發程式設計

構造并發程序最簡單的方法就是用程序:在父程序中接受用戶端連接配接的請求然後建立一個新的子程序來為每個新的用戶端提供服務

12.1.1基于程序的并發伺服器

資訊安全系統設計基礎第十三周學習總結

12.1.2關于程序的優劣

父子程序共享資訊狀态:共享檔案表,單步共享使用者位址空間。優點是可以防止覆寫程序的虛拟存儲器;缺點是使用顯式的程序間通訊,速度較慢

12.2基于I/O多路複用的并發程式設計

基本思路:使用select函數,要求核心挂起程序,隻有在一個或多個I/O事件發生後,才将控制傳回給應用程式。

資訊安全系統設計基礎第十三周學習總結

select函數有兩個輸入:一個稱為讀集合的描述符字元結合和該讀集合的基數

12.2.1基于I/O多路複用的并發事件驅動伺服器

不嚴格的說一個狀态機就是一組狀态,輸入事件和轉移

流程:

select函數檢測到輸入事件
add_client函數建立新狀态機
check_clients函數執行狀态轉移(在課本的例題中是回送輸入行),并且完成時删除該狀态機。
           
資訊安全系統設計基礎第十三周學習總結

函數:

init_pool:初始化用戶端池
add_client:添加一個新用戶端到火丁用戶端池中
check_clients:回送來自每個準備好的已連接配接描述符的一個文本行
           

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

1.優點

相較基于程序的設計,給了程式員更多的對程式程式的控制
運作在單一程序上下文中,是以每個邏輯流都可以通路該程序的全部位址空間,共享資料容易實作
可以使用GDB調試
高效
           

2.缺點

編碼複雜
不能充分利用多核處理器
           

12.3基于線程的并發程式設計

線程:就是運作在程序上下文中的邏輯流。混合了以上兩種方法

每個程序都有自己的線程上下文,包括:一個唯一的整數線程ID——TID、棧、棧指針、程式計數器、通用目的寄存器、條件碼。

12.3.1線程執行模型

主線程:在每個程序開始生命周期時都是單一線程——主線程,與其他程序的差別僅有:它總是程序中第一個運作的線程。

對等線程:某時刻主線程建立,之後兩個線程并發運作。

每個對等線程都能讀寫相同的共享資料。

資訊安全系統設計基礎第十三周學習總結

主線程切換到對等線程的原因:

·主線程執行一個慢速系統調用,如read或sleep
·被系統的間隔計時器中斷
           

12.3.2 posix線程

POSIX線程是在C程式中處理線程的一個标準接口

資訊安全系統設計基礎第十三周學習總結

12.3.3建立線程

線程通過調用pthread_create函數建立其他線程

資訊安全系統設計基礎第十三周學習總結

建立一個新的線程,帶着一個輸入變量arg,在新線程的上下文運作線程例程f。

attr預設為NULL

參數tid中包含新建立線程的ID

12.3.4終止線程

終止線程的幾個方式:

隐式終止:頂層的線程例程傳回

顯示終止:調用pthread_exit函數

#include<pthread.h>
void pthread_exit(void *thread_return)
           

某個對等線程調用Unix的exit函數,會終止程序與其相關線程

另一個對等線程通過以目前線程ID作為參數調用pthread_cancle來終止目前線程

12.3.5 回收已終止線程的資源

pthread_join函數:

#include <pthread.h>
int pthread_join(pthread_t tid,void **thrad_return);
           

這個函數會阻塞,知道線程tid終止,将線程例程傳回的(void*)指針指派為thread_return指向的位置,然後回收已終止線程占用的所有存儲器資源

12.3.6 分離線程

在任何一個時間點上,一個線程是可結合或者分離的

可結合的線程

能夠被其他線程收回其資源和殺死
被收回錢,它的存儲器資源沒有被釋放
每個可結合線程要麼被其他線程顯式的收回,要麼通過調用pthread_detach函數被分離
           

分離的線程

不能被其他線程回收或殺死
存儲器資源在它終止時由系統自動釋放
           

12.3.7 初始化線程

pthread_once 允許你初始化與線程例程相關的狀态

#include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
           

once_control是一個全局或者靜态變量

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

一個變量是共享的,當且僅當多個線程引用這個變量的某個執行個體。

12.4.1 線程存儲器模型

寄存器從不共享,虛拟存儲器總是共享的。

12.4.2将變量映射到存儲器

根據存儲器類型被映射到虛拟存儲器中

1、全局變量

定義在函數之外
運作時,虛拟存儲器的讀寫區域隻包括每個全局變量的一個執行個體,任何線程都可以引用
           

2、本地自動變量

定義在函數内部但是沒有static屬性的變量
運作時,每個線程的站都包括他自己的所有本地自動變量的執行個體
           

3、本地靜态變量

定義在函數内部并且有static屬性的變量
運作時,和全局變量一樣
           

12.4.3 共享變量

我們說一個變量是共享的,當且僅當他的一個執行個體被一個以上的線程引用

12.5 用信号量同步線程

共享線程十分友善但是會帶來同步錯誤的可能性,一般而言,沒有辦法預測作業系統是否将為你的線程選擇一個正确的順序。

12.5.1 進度圖

進度圖:是将n個并發線程的執行模型化為一條n維笛卡爾空間中的軌迹線,原點對應于沒有任何線程完成一條指令的初始狀态。

進度圖将指令執行模式化為一種狀态到另一種狀态的轉換。轉換被表示為一條從一點到相鄰點的有向邊

互斥通路:臨界區不應該和其他程序的臨界區交替使用

不安全區:兩個臨界區的交集形成的狀态空間區域

資訊安全系統設計基礎第十三周學習總結

12.5.2 信号量

信号量:是具有非負整數值的全局變量,隻能由兩種特殊的操作來處理:P和V。

資訊安全系統設計基礎第十三周學習總結

注意

每個信号量在使用之前必須初始化
V的定義中沒有定義等待形成被重新啟動的順序,唯一的要求是V必須隻能啟動一個正在等待的線程
           
資訊安全系統設計基礎第十三周學習總結

12.5.3 使用信号量來實作互斥

基本思想:将每個共享變量(或者一組相關的共享變量)與一個信号量s(初始為1)聯系起來,然後用P和V操作将相應的臨界區包圍起來。用這種方式保護共享變量的信号叫做二進制信号量。

概念:

互斥鎖:以提供互斥為目的的二進制信号量
加鎖:對一個互斥鎖執行P操作
解鎖;對一個互斥鎖執行V操作
計數信号量:被用作一組可用資源的計數器的信号量
禁止區:由于信号量的不變性,沒有實際可能的軌迹能夠包含禁止區中的狀态。
           

12.5.4 利用信号量來排程共享資源

這部分的内容在作業系統中有學過,比較了解

1、生産者和消費者

資訊安全系統設計基礎第十三周學習總結

2、讀者和寫者

資訊安全系統設計基礎第十三周學習總結

12.5.5 綜合:基于預線程化的并發伺服器

資訊安全系統設計基礎第十三周學習總結

12.6 使用線程提高并行性

所有程式的集合能夠劃分成不相交的順序程式集合和并發程式集合。寫順序程式隻有一條邏輯流。并發程式有多條邏輯流。并行程式是一個運作早多個處理器上的并發程式。是以,并行程式的集合是并發程式集合的真子集。

12.7 其他并發問題

12.7.1 線程安全

一個函數被稱為線程安全,當且僅當被多個并發線程反複調用時會一直産生正确的結果

不安全函數類:

1、不保護共享變量的函數

利用像P和V這樣的同步操作來保護共享的變量
優點:在調用抽程式中不需要做任何修改
缺點:同步操作将減慢程式執行的時間
           

2、保持跨越多個調用的狀态的函數

一個僞随機數産生器是這類線程不安全函數的簡單例子

3、傳回指向靜态變量的指針的函數

某些函數将計算結果放在一個靜态變量中,然後傳回一個指向這個變量的指針,如果并發線程中調用這些函數,那麼可能會發生災難

處理方法:

第一種:重寫函數,使的調用者傳遞存放結果的變量的位址,修改函數的源代碼
第二種:加鎖—拷貝,将線程的不安全函數與互斥鎖聯系起來
           

4、調用線程不安全函數的函數

資訊安全系統設計基礎第十三周學習總結

12.7.2 可重入性

當他們被多個線程調用時不會引用任何共享資料

1、顯式可重入的:

所有函數參數都是傳值傳遞,沒有指針,并且所有的資料引用都是本地的自動棧變量,沒有引用靜态或全劇變量。

2、隐式可重入的:

調用線程小心的傳遞指向非共享資料的指針。

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

unix系統通過大多數線程不安全函數的可重入版本,可重入版本的名字以_r為字尾結尾。

12.7.4 競争

1、 競争發生的原因:

一個程式的正确性依賴于一個線程要在另一個線程到達y點之前到達它的控制流中的x點。也就是說,程式員假定線程會按照某種特殊的軌迹穿過執行狀态空間,忘了一條準則規定:線程化的程式必須對任何可行的軌迹線都正确工作。

2、消除方法:

動态的為每個整數ID配置設定一個獨立的塊,并且傳遞給線程例程一個指向這個塊的指針

12.7.5 鎖死

競争和鎖死都在作業系統中有學過

資訊安全系統設計基礎第十三周學習總結