20145203 《信息安全系统设计基础》第十三周学习总结
20145203 《信息安全系統(tǒng)設(shè)計(jì)基礎(chǔ)》第十三周學(xué)習(xí)總結(jié)
第十二章 并發(fā)編程
教材學(xué)習(xí)內(nèi)容總結(jié)
緒論
三種基本的構(gòu)造并發(fā)程序的方法:
①進(jìn)程:
每個(gè)邏輯控制流是一個(gè)進(jìn)程,由內(nèi)核進(jìn)行調(diào)度,進(jìn)程有獨(dú)立的虛擬地址空間
②I/O多路復(fù)用:
邏輯流被模型化為狀態(tài)機(jī),所有流共享同一個(gè)地址空間
③線程:
運(yùn)行在單一進(jìn)程上下文中的邏輯流,由內(nèi)核進(jìn)行調(diào)度,共享同一個(gè)虛擬地址空間
第一節(jié) 基于進(jìn)程的并發(fā)編程
構(gòu)造并發(fā)程序最簡(jiǎn)單的方法——用進(jìn)程
1、常用函數(shù)如下:
- fork
- exec
- waitpid
2、構(gòu)造并發(fā)服務(wù)器
在父進(jìn)程中接受客戶端連接請(qǐng)求,然后創(chuàng)建一個(gè)新的子進(jìn)程來(lái)為每個(gè)新客戶端提供服務(wù)。
需要注意的事情:
①父進(jìn)程需要關(guān)閉它的已連接描述符的拷貝(子進(jìn)程也需要關(guān)閉)
②必須要包括一個(gè)SIGCHLD處理程序來(lái)回收僵死子進(jìn)程的資源
③父子進(jìn)程之間共享文件表,但是不共享用戶地址空間。
3、進(jìn)程的獨(dú)立地址空間
①優(yōu)點(diǎn):防止虛擬存儲(chǔ)器被錯(cuò)誤覆蓋
②缺點(diǎn):開(kāi)銷高,共享狀態(tài)信息才需要IPC機(jī)制
第二節(jié) 基于I/O多路復(fù)用的并發(fā)編程
就是使用select函數(shù)要求內(nèi)核掛起進(jìn)程,只有在一個(gè)或多個(gè)I/O事件發(fā)生后,才將控制返回給應(yīng)用程序。
1、select函數(shù):select函數(shù)處理類型為fd_set的集合,即描述符集合,并在邏輯上描述為一個(gè)大小為n的位向量,每一位b[k]對(duì)應(yīng)描述符k,但當(dāng)且僅當(dāng)b[k]=1,描述符k才表明是描述符集合的一個(gè)元素。
2、描述符能做的三件事:
- 分配他們
- 將一個(gè)此種類型的變量賦值給另一個(gè)變量
- 用FD_ZERO、FD_SET、FD_CLR和FD_ISSET宏指令來(lái)修改和檢查它們
3、什么時(shí)候可以讀?
當(dāng)且僅當(dāng)一個(gè)從該描述符讀取一個(gè)字節(jié)的請(qǐng)求不會(huì)阻塞時(shí)
注意:
每次調(diào)用select函數(shù)時(shí)都需要更新讀集合
4、基于I/O多路復(fù)用的并發(fā)事件驅(qū)動(dòng)服務(wù)器
事件驅(qū)動(dòng)程序:將邏輯流模型化為狀態(tài)機(jī)。
狀態(tài)機(jī):
- 狀態(tài):等待描述符d[k]準(zhǔn)備好可讀
- 輸入事件:描述符d[k]準(zhǔn)備好,可以讀了
- 轉(zhuǎn)移:從描述符d[k]讀一個(gè)文本行
整體的流程是:
- select函數(shù)檢測(cè)到輸入事件
- add_client函數(shù)創(chuàng)建新?tīng)顟B(tài)機(jī)
- check_clients函數(shù)執(zhí)行狀態(tài)轉(zhuǎn)移(在課本的例題中是回送輸入行),并且完成時(shí)刪除該狀態(tài)機(jī)。
用到的函數(shù):
- init_pool:初始化客戶端池
- add_client:添加一個(gè)新的客戶端到活動(dòng)客戶端池中
- check_clients:回送來(lái)自每個(gè)準(zhǔn)備好的已連接描述符的一個(gè)文本行
5、I/O多路復(fù)用技術(shù)的優(yōu)劣
①優(yōu)點(diǎn)
- 相較基于進(jìn)程的設(shè)計(jì),給了程序員更多的對(duì)程序程序的控制
- 運(yùn)行在單一進(jìn)程上下文中,所以每個(gè)邏輯流都可以訪問(wèn)該進(jìn)程的全部地址空間,共享數(shù)據(jù)容易實(shí)現(xiàn)
- 可以使用GDB調(diào)試
- 高效
②缺點(diǎn)
- 編碼復(fù)雜
- 不能充分利用多核處理器
第三節(jié) 基于線程的并發(fā)編程
這種模式混合了以上兩種方法:像進(jìn)程流一樣由內(nèi)核進(jìn)行調(diào)度,又像I/O多路復(fù)用流一樣共享同一個(gè)虛擬地址空間
線程:就是運(yùn)行在進(jìn)程上下文中的邏輯流。
1、每個(gè)線程都有它自己的線程上下文:
- 一個(gè)唯一的整數(shù)線程ID——TID
- 棧
- 棧指針
- 程序計(jì)數(shù)器
- 通用目的寄存器
- 條件碼
2、線程執(zhí)行模型
①主線程
在每個(gè)進(jìn)程開(kāi)始生命周期時(shí)都是單一線程——主線程,與其他進(jìn)程的區(qū)別僅有:它總是進(jìn)程中第一個(gè)運(yùn)行的線程。
②對(duì)等線程
某時(shí)刻主線程創(chuàng)建,之后兩個(gè)線程并發(fā)運(yùn)行。每個(gè)對(duì)等線程都能讀寫(xiě)相同的共享數(shù)據(jù)。
3、主線程切換到對(duì)等線程的原因:
①主線程執(zhí)行一個(gè)慢速系統(tǒng)調(diào)用,如read或sleep
② 被系統(tǒng)的間隔計(jì)時(shí)器中斷
注意:
①切換方式:上下文切換
②對(duì)等線程執(zhí)行一段時(shí)間后會(huì)控制傳遞回主線程
4、線程和進(jìn)程的區(qū)別
- 線程的上下文切換比進(jìn)程快得多
- 組織形式:
進(jìn)程:嚴(yán)格的父子層次
線程:一個(gè)進(jìn)程相關(guān)線程組成對(duì)等(線程)池,和其他進(jìn)程的線程獨(dú)立開(kāi)來(lái)。一個(gè)線程可以殺死它的任意對(duì)等線程,或者等待他的任意對(duì)等線程終止。
5、Posix線程
Posix線程是C程序中處理線程的一個(gè)標(biāo)準(zhǔn)接口。基本用法是:
- 線程的代碼和本地?cái)?shù)據(jù)被封裝在一個(gè)線程例程中
- 每個(gè)線程例程都以一個(gè)通用指針為輸入,并返回一個(gè)通用指針。
這里需要提到一個(gè)萬(wàn)能函數(shù)的概念。
************************************************************************************************
萬(wàn)能函數(shù):
void func(void parameter)
typedef void (uf)(void para)
使用思想:即輸入的是指針,指向真正想要傳到函數(shù)里的數(shù)據(jù),如果只有一個(gè)就直接讓指針指向這個(gè)數(shù)據(jù),如果是很多就將它們放到一個(gè)結(jié)構(gòu)體中,讓指針指向這個(gè)結(jié)構(gòu)體。
線程例程也是這樣的。
************************************************************************************************
6、創(chuàng)建線程
①.創(chuàng)建線程:pthread_create函數(shù)
#include <pthread.h>
typedef void (func)(void );
創(chuàng)建一個(gè)新的線程,帶著一個(gè)輸入變量arg,在新線程的上下文運(yùn)行線程例程f。
attr默認(rèn)為NULL
參數(shù)tid中包含新創(chuàng)建線程的ID
7、查看線程ID——pthread_self函數(shù)
#include <pthread.h>
pthread_t pthread_self(void);返回調(diào)用者的線程ID(TID)8、終止線程
①終止線程的幾個(gè)方式:
- 隱式終止:頂層的線程例程返回
- 顯示終止:調(diào)用pthread_exit函數(shù)
*如果主線程調(diào)用,會(huì)先等待所有其他對(duì)等線程終止,再終止主線程和整個(gè)進(jìn)程,返回值為pthread_return - 某個(gè)對(duì)等線程調(diào)用Unix的exit函數(shù),會(huì)終止進(jìn)程與其相關(guān)線程
- 另一個(gè)對(duì)等線程通過(guò)以當(dāng)前線程ID作為參數(shù)調(diào)用pthread_cancle來(lái)終止當(dāng)前線程
②pthread_exit函數(shù)
#include <pthread.h>void pthread_exit(void *thread_return);若成功返回0,出錯(cuò)為非0③pthread_cancle函數(shù)
#include <pthread.h>void pthread_cancle(pthread_t tid);若成功返回0,出錯(cuò)為非09、回收已終止線程的資源:pthread_join函數(shù)
#include <pthread.h>int pthread_join(pthread_t tid,void **thrad_return);這個(gè)函數(shù)會(huì)阻塞,直到線程tid終止,將線程例程返回的(void*)指針賦值為thread_return指向的位置,然后回收已終止線程占用的所有存儲(chǔ)器資源
10、分離線程
在任何一個(gè)時(shí)間點(diǎn)上,線程是可結(jié)合的,或是分離的。
①可結(jié)合的線程
- 能夠被其他線程收回其資源和殺死
- 被收回錢(qián),它的存儲(chǔ)器資源沒(méi)有被釋放
- 每個(gè)可結(jié)合線程要么被其他線程顯式的收回,要么通過(guò)調(diào)用pthread_detach函數(shù)被分離
②分離的線程
- 不能被其他線程回收或殺死
- 存儲(chǔ)器資源在它終止時(shí)由系統(tǒng)自動(dòng)釋放
③pthread_detach函數(shù)
#include <pthread.h>void pthread_detach(pthread_t tid);若成功返回0,出錯(cuò)為非0這個(gè)函數(shù)可以分離可結(jié)合線程tid。
線程能夠通過(guò)以pthread_self()為參數(shù)的pthread_detach調(diào)用來(lái)分離他們自己。
11、初始化線程:pthread_once函數(shù)
#include <pthread.h> pthread_once_t once_control = PTHREAD_ONCE_INIT;int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));總是返回012、基于線程的并發(fā)服務(wù)器中的注意事項(xiàng)
①調(diào)用pthread_create時(shí),如何將已連接描述符傳遞給對(duì)等進(jìn)程?
傳遞一個(gè)指向這個(gè)描述符的指針。
②競(jìng)爭(zhēng)問(wèn)題?
見(jiàn)第七節(jié)。
③避免存儲(chǔ)器泄露?
必須分離每個(gè)線程,使它終止時(shí)它的存儲(chǔ)器資源能被收回。
第四節(jié) 多線程程序中的共享變量
一個(gè)變量是共享的,當(dāng)且僅當(dāng)多個(gè)線程引用這個(gè)變量的某個(gè)實(shí)例。
1、線程存儲(chǔ)器模型
注意:寄存器從不共享,虛擬存儲(chǔ)器總是共享的。
2、將變量映射到存儲(chǔ)器
3、共享變量
變量v是共享的——當(dāng)且僅當(dāng)它的一個(gè)實(shí)例被一個(gè)以上的線程引用。
第五節(jié) 用信號(hào)量同步線程
一般而言,沒(méi)有辦法預(yù)測(cè)操作系統(tǒng)是否將為你的線程選擇一個(gè)正確的順序。
所以——進(jìn)度圖
1、進(jìn)度圖
進(jìn)度圖是將n個(gè)并發(fā)線程的執(zhí)行模型化為一條n維笛卡爾空間中的軌跡線,原點(diǎn)對(duì)應(yīng)于沒(méi)有任何線程完成一條指令的初始狀態(tài)。
當(dāng)n=2時(shí),狀態(tài)比較簡(jiǎn)單,是比較熟悉的二維坐標(biāo)圖,橫縱坐標(biāo)各代表一個(gè)線程,而轉(zhuǎn)換被表示為有向邊
①轉(zhuǎn)換規(guī)則:
- 合法的轉(zhuǎn)換是向右或者向上,即某一個(gè)線程中的一條指令完成
- 兩條指令不能在同一時(shí)刻完成,即不允許出現(xiàn)對(duì)角線
- 程序不能反向運(yùn)行,即不能出現(xiàn)向下或向左
而一個(gè)程序的執(zhí)行歷史被模型化為狀態(tài)空間中的一條軌跡線。
②線程循環(huán)代碼的分解:
- H:在循環(huán)頭部的指令塊
- L:加載共享變量cnt到線程i中寄存器%eax的指令。
- U:更新(增加)%eax的指令
- S:將%eax的更新值存回到共享變量cnt的指令
- T:循環(huán)尾部的指令塊
③幾個(gè)概念:
- 臨界區(qū):對(duì)于線程i,操作共享變量cnt內(nèi)容的指令L,U,S構(gòu)成了一個(gè)關(guān)于共享變量cnt的臨界區(qū)。
- 不安全區(qū):兩個(gè)臨界區(qū)的交集形成的狀態(tài)
- 安全軌跡線:繞開(kāi)不安全區(qū)的軌跡線
2、信號(hào)量
需要注意的是,每個(gè)信號(hào)量在使用前必須初始化。
3、使用信號(hào)量來(lái)實(shí)現(xiàn)互斥
①基本思想
將每個(gè)共享變量(或者一組相關(guān)的共享變量)與一個(gè)信號(hào)量s(初始為1)聯(lián)系起來(lái),然后用P和V操作將相應(yīng)的臨界區(qū)包圍起來(lái)。
②幾個(gè)概念
- 二元信號(hào)量:用這種方式來(lái)保護(hù)共享變量的信號(hào)量叫做二元信號(hào)量,取值總是0或者1.
- 互斥鎖:以提供互斥為目的的二元信號(hào)量
- 加鎖:對(duì)一個(gè)互斥鎖執(zhí)行P操作
- 解鎖;對(duì)一個(gè)互斥鎖執(zhí)行V操作
- 計(jì)數(shù)信號(hào)量:被用作一組可用資源的計(jì)數(shù)器的信號(hào)量
- 禁止區(qū):由于信號(hào)量的不變性,沒(méi)有實(shí)際可能的軌跡能夠包含禁止區(qū)中的狀態(tài)。
4、利用信號(hào)量來(lái)調(diào)度共享資源
①信號(hào)量的物理意義
- s.count >0表示還可執(zhí)行wait(s)而不會(huì)阻塞的進(jìn)程數(shù)(可用資源數(shù))。每執(zhí)行一次wait(s)操作,就意味著請(qǐng)求分配一個(gè)單位的資源。
- 當(dāng)s.count ≤0時(shí),表示已無(wú)資源可用,因此請(qǐng)求該資源的進(jìn)程被阻塞。此時(shí),s.count的絕對(duì)值等于該信號(hào)量阻塞隊(duì)列中的等待進(jìn)程數(shù)。執(zhí)行一次signal操作,就意味著釋放一個(gè)單位的資源。若s.count<0,表示s.queue隊(duì)列中還有被阻塞的進(jìn)程,需要喚醒該隊(duì)列中的第一個(gè)進(jìn)程,將它轉(zhuǎn)移到就緒隊(duì)列中。
②常見(jiàn)問(wèn)題
這里的常見(jiàn)問(wèn)題有生產(chǎn)者-消費(fèi)者問(wèn)題,和讀者-寫(xiě)者問(wèn)題。詳見(jiàn)課本P.670
第七節(jié) 其他并發(fā)問(wèn)題
1、線程安全性
一個(gè)線程是安全的,當(dāng)且僅當(dāng)被多個(gè)并發(fā)線程反復(fù)的調(diào)用時(shí),它會(huì)一直產(chǎn)生正確的結(jié)果。
2、四個(gè)不相交的線程不安全函數(shù)類以及應(yīng)對(duì)措施:
- 不保護(hù)共享變量的函數(shù)——用P和V這樣的同步操作保護(hù)共享變量
- 保持跨越多個(gè)調(diào)用的狀態(tài)的函數(shù)——重寫(xiě),不用任何static數(shù)據(jù)。
- 返回指向靜態(tài)變量的指針的函數(shù)——①重寫(xiě);②使用加鎖-拷貝技術(shù)。
- 調(diào)用線程不安全函數(shù)的函數(shù)——參考之前三種
3、可重入性
①顯式可重入的:
所有函數(shù)參數(shù)都是傳值傳遞,沒(méi)有指針,并且所有的數(shù)據(jù)引用都是本地的自動(dòng)棧變量,沒(méi)有引用靜態(tài)或全劇變量。
②隱式可重入的:
調(diào)用線程小心的傳遞指向非共享數(shù)據(jù)的指針。
4、競(jìng)爭(zhēng)
①競(jìng)爭(zhēng)發(fā)生的原因:
一個(gè)程序的正確性依賴于一個(gè)線程要在另一個(gè)線程到達(dá)y點(diǎn)之前到達(dá)它的控制流中的x點(diǎn)。也就是說(shuō),程序員假定線程會(huì)按照某種特殊的軌跡穿過(guò)執(zhí)行狀態(tài)空間,忘了一條準(zhǔn)則規(guī)定:線程化的程序必須對(duì)任何可行的軌
跡線都正確工作。
②消除方法:
動(dòng)態(tài)的為每個(gè)整數(shù)ID分配一個(gè)獨(dú)立的塊,并且傳遞給線程例程一個(gè)指向這個(gè)塊的指針
5、死鎖:
一組線程被阻塞了,等待一個(gè)永遠(yuǎn)也不會(huì)為真的條件。
①條件
②解決死鎖的方法
a.不讓死鎖發(fā)生:
- 靜態(tài)策略:設(shè)計(jì)合適的資源分配算法,不讓死鎖發(fā)生---死鎖預(yù)防;
- 動(dòng)態(tài)策略:進(jìn)程在申請(qǐng)資源時(shí),系統(tǒng)審查是否會(huì)產(chǎn)生死鎖,若會(huì)產(chǎn)生死鎖則不分配---死鎖避免。
b.讓死鎖發(fā)生:
進(jìn)程申請(qǐng)資源時(shí)不進(jìn)行限制,系統(tǒng)定期或者不定期檢測(cè)是否有死鎖發(fā)生,當(dāng)檢測(cè)到時(shí)解決死鎖----死鎖檢測(cè)與解除。
教材學(xué)習(xí)中的問(wèn)題和解決過(guò)程
問(wèn)題一:為什么要用結(jié)構(gòu)體來(lái)存放標(biāo)量IP地址?
解決:把一個(gè)標(biāo)量地址存放在結(jié)構(gòu)中,是套接字早期實(shí)現(xiàn)的不幸產(chǎn)物。位IP地址定義一個(gè)標(biāo)量類型應(yīng)該跟更有意義,但是現(xiàn)在更該已經(jīng)太遲了,因?yàn)橐呀?jīng)有大量的應(yīng)用是基于此的了。
問(wèn)題二:臨界區(qū)使用原則(互斥條件)
使用原則:
- 有空讓進(jìn):如果臨界區(qū)空閑,則只要有進(jìn)程申請(qǐng)就立即讓其進(jìn)入;
- 無(wú)空等待:每次只允許一個(gè)進(jìn)程處于臨界區(qū);
- 多中擇一:當(dāng)沒(méi)有進(jìn)程在臨界區(qū),而同時(shí)有多個(gè)進(jìn)程要求進(jìn)入臨界區(qū),只能讓其中之一進(jìn)入臨界區(qū),其他進(jìn)程必須等待;
- 讓權(quán)等待:進(jìn)入臨界區(qū)的進(jìn)程,不能在臨界區(qū)內(nèi)長(zhǎng)時(shí)間阻塞等待某事件,使其它進(jìn)程在臨界區(qū)外無(wú)限期等待;
不能限制進(jìn)程的并發(fā)數(shù)量和執(zhí)行進(jìn)度。
問(wèn)題三:信號(hào)量實(shí)現(xiàn)互斥的基本原理
基本原理:
- 兩個(gè)或多個(gè)進(jìn)程通過(guò)傳遞信號(hào)進(jìn)行合作,可以迫使進(jìn)程在某個(gè)位置暫時(shí)停止執(zhí)行(阻塞等待),直到它收到一個(gè)可以“向前推進(jìn)”的信號(hào)(被喚醒);
- 將實(shí)現(xiàn)信號(hào)燈作用的變量稱為信號(hào)量,常定義為記錄型變量s,其一個(gè)域?yàn)檎?#xff0c;另一個(gè)域?yàn)殛?duì)列,其元素為等待該信號(hào)量的阻塞進(jìn)程(FIFO)。
信號(hào)量定義:
type semaphore=recordcount: integer;queue: list of process end; var s:semaphore;
定義對(duì)信號(hào)量的兩個(gè)原子操作——P和V
P(wait)
wait(s)
s.count :=s.count-1;
if s.count<0 then
begin
進(jìn)程阻塞;
進(jìn)程進(jìn)入s.queue隊(duì)列;
end;
V(signal)
signal(s)
s.count :=s.count+1;
if s.count ≤0 then
begin
喚醒隊(duì)首進(jìn)程;
將進(jìn)程從s.queue阻塞隊(duì)列中移出;
end;
其它(思想、感悟)
本周內(nèi)容中有很多在操作系統(tǒng)課程和java web編程課程中已經(jīng)詳細(xì)講,但是需要注意的是,課本中講述問(wèn)題的方式與操作系統(tǒng)課程中有些不同,本課更多是從代碼角度,兩者需要相輔相成,互相促進(jìn)理解,這樣使得學(xué)習(xí)起來(lái)更輕松,也更全面。
本周代碼托管截圖
代碼鏈接
學(xué)習(xí)進(jìn)度條
| 目標(biāo) | 5000行 | 30篇 | 400小時(shí) | |
| 第一周 | 150/150 | 1/2 | 20/20 | |
| 第二周 | 200/350 | 1/2 | 24/44 | |
| 第三周 | 150/500 | 1/3 | 20/64 | |
| 第五周 | 300/800 | 1/4 | 15/79 | |
| 第六周 | 500/1300 | 1/5 | 20/99 | |
| 第七周 | 200/1500 | 1/6 | 21/120 | |
| 第九周 | 210/1710 | 1/9 | 10/130 | |
| 第十周 | 530/2240 | 2/11 | 20/150 | |
| 第十一周 | 900/3140 | 1/12 | 30/180 | |
| 第十三周 | 1100/4240 | 1/17 | 30/210 |
參考資料
- 《深入理解計(jì)算機(jī)系統(tǒng)V2》學(xué)習(xí)指導(dǎo)
- ...
轉(zhuǎn)載于:https://www.cnblogs.com/GZSdeboke/p/6160947.html
總結(jié)
以上是生活随笔為你收集整理的20145203 《信息安全系统设计基础》第十三周学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: XidianOJ 1176 ship
- 下一篇: ELK+logback搭建日志系统