20135203齐岳 信息安全系统设计基础第十三周学习总结
20135203齊岳 信息安全系統(tǒng)設(shè)計(jì)基礎(chǔ)第十三周學(xué)習(xí)總結(jié)
學(xué)習(xí)計(jì)時(shí):8/9共小時(shí)(計(jì)劃/實(shí)際)
讀書:4/5
代碼:1/1
作業(yè):1/1
博客:2/2
第十二章 并發(fā)編程
一、學(xué)習(xí)目標(biāo)
二、學(xué)習(xí)任務(wù)
三、學(xué)習(xí)過程
如果邏輯控制流在時(shí)間上重疊,那么他們就是并發(fā)的。應(yīng)用級(jí)并發(fā)在以下情況中發(fā)揮作用:
- 訪問慢速I/O設(shè)備。
- 與人交互。
- 通過推遲工作以降低延遲。
- 服務(wù)多個(gè)網(wǎng)絡(luò)客戶端。
- 在多核機(jī)器上進(jìn)行并行計(jì)算。
使用應(yīng)用級(jí)并發(fā)的應(yīng)用程序稱為并發(fā)程序。現(xiàn)代操作系統(tǒng)提供了三種基本的構(gòu)造并發(fā)程序的方法:
- 進(jìn)程。每個(gè)邏輯控制流都是一個(gè)進(jìn)程,由內(nèi)核來(lái)調(diào)度和維護(hù)。控制流使用顯式的進(jìn)程間通信(IPC)機(jī)制。
- I/O多路復(fù)用。應(yīng)用程序在一個(gè)進(jìn)程的上下文中顯式地調(diào)度他們自己的邏輯流。所有的流都共享同一個(gè)地址空間。
- 線程。線程是運(yùn)行在一個(gè)單一進(jìn)程上下文中的邏輯流,由內(nèi)核進(jìn)行調(diào)度。
12.1 基于進(jìn)程的并發(fā)編程
基于進(jìn)程的并發(fā)服務(wù)器
- 使用SIGCHLD處理程序來(lái)回收僵死子進(jìn)程的資源。
- 父進(jìn)程必須關(guān)閉他們各自的connfd拷貝(已連接的描述符),避免存儲(chǔ)器泄露。
- 因?yàn)樘捉幼值奈募肀眄?xiàng)中的引用計(jì)數(shù),直到父子進(jìn)程的connfd都關(guān)閉了,到客戶端的連接才會(huì)終止。
關(guān)于進(jìn)程的優(yōu)劣
- 在父子進(jìn)程之間共享狀態(tài)信息,通過共享文件表,但是不共享用戶地址空間。
- 使用顯式的進(jìn)程間通信(IPC)機(jī)制。但開銷很高,往往比較慢。
基于I/O多路復(fù)用的并發(fā)編程
使用select函數(shù),要求內(nèi)核掛起進(jìn)程,只有在一個(gè)或多個(gè)I/O事件發(fā)生后,才將控制返回給應(yīng)用程序。
int select(int n,fd_set *fdset,NULL,NULL,NULL);返回已經(jīng)準(zhǔn)備好的描述符的非0的個(gè)數(shù),若出錯(cuò)則為-1。select函數(shù)處理類型為fd_set的集合,叫做描述符集合,看做一個(gè)大小為n位的向量:
bn-1,......,b1,b0對(duì)描述符集合的處理方法:
- 分配他們
- 將一個(gè)此種類型的變量賦值給另一個(gè)變量
- 用FD_ZERO,FD_SET,FD_CLR和FD_ISSET宏指令來(lái)修改和檢查他們。
基于I/O多路復(fù)用的并發(fā)事件驅(qū)動(dòng)服務(wù)器
I/O多路復(fù)用可以用作事件并發(fā)驅(qū)動(dòng)程序的基礎(chǔ)。
狀態(tài)機(jī):一組狀態(tài)、輸入事件、輸出事件和轉(zhuǎn)移。
自循環(huán):同一輸入和輸出狀態(tài)之間的轉(zhuǎn)移。
I/O多路復(fù)用技術(shù)的優(yōu)劣
- 相比基于進(jìn)程的設(shè)計(jì)給了程序員更多的對(duì)進(jìn)程行為的控制,運(yùn)行在單一進(jìn)程上下文中,每個(gè)邏輯流都能訪問全部的地址空間,在流之間共享數(shù)據(jù)很容易。
- 編碼復(fù)雜,隨著并發(fā)粒度的減小,復(fù)雜性還會(huì)上升。粒度:每個(gè)邏輯流每個(gè)時(shí)間片執(zhí)行的指令數(shù)量。
12.3 基于線程的并發(fā)編程
線程:運(yùn)行在進(jìn)程上下文中的邏輯流,由內(nèi)核自動(dòng)調(diào)度,有自己的線程上下文,包括一個(gè)唯一的整數(shù)線程ID,棧、棧指針、程序計(jì)數(shù)器、通用目的寄存器和條件碼。所有運(yùn)行在一個(gè)進(jìn)程里的線程共享該進(jìn)程的整個(gè)虛擬地址空間。
線程執(zhí)行模型
每個(gè)進(jìn)程開始生命周期時(shí)都是單一線程(主線程),在某一時(shí)刻創(chuàng)建一個(gè)對(duì)等線程,從此開始并發(fā)地運(yùn)行,最后,因?yàn)橹骶€程執(zhí)行一個(gè)慢速系統(tǒng)調(diào)用,或者被中斷,控制就會(huì)通過上下文切換傳遞到對(duì)等線程。
Posix線程
Posix線程是C語(yǔ)言中處理線程的一個(gè)標(biāo)準(zhǔn)接口,允許程序創(chuàng)建、殺死和回收線程,與對(duì)等線程安全的共享數(shù)據(jù)。
線程的代碼和本地?cái)?shù)據(jù)被封裝在一個(gè)線程例程中,
創(chuàng)建線程
線程通過調(diào)用pthread_create來(lái)創(chuàng)建其他線程。
int pthread_create(pthread_t *tid,pthread_attr_t *attr,func *f,void *arg);成功則返回0,出錯(cuò)則為非零當(dāng)函數(shù)返回時(shí),參數(shù)tid包含新創(chuàng)建的線程的ID,新線程可以通過調(diào)用pthread_self函數(shù)來(lái)獲得自己的線程ID。
pthread_t pthread_self(void);返回調(diào)用者的線程ID。終止線程
一個(gè)線程是通過以下方式之一來(lái)終止的。
- 當(dāng)頂層的線程例程返回時(shí),線程會(huì)隱式地終止。
通過調(diào)用pthread_exit函數(shù),線程會(huì)顯式地終止
void pthread_exit(void *thread_return);
回收已終止的線程資源
線程通過調(diào)用pthread_join函數(shù)等待其他線程終止。
int pthread_join(pthread_t tid,void **thread_return);成功則返回0,出錯(cuò)則為非零分離線程
在任何一個(gè)時(shí)間點(diǎn)上,線程是可結(jié)合或可分離的。一個(gè)可結(jié)合的線程能夠被其他線程收回其資源和殺死,在被回收之前,它的存儲(chǔ)器資源是沒有被釋放的。分離的線程則相反,資源在其終止時(shí)自動(dòng)釋放。
int pthread_deacth(pthread_t tid);成功則返回0,出錯(cuò)則為非零初始化線程
pthread_once允許初始化與線程例程相關(guān)的狀態(tài)。
pthread_once_t once_control=PTHREAD_ONCE_INIT; int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));總是返回012.4 多線程程序中的共享變量
一個(gè)變量是共享的。當(dāng)且僅當(dāng)多個(gè)線程引用這個(gè)變量的某個(gè)實(shí)例。
線程存儲(chǔ)器模型
- 每個(gè)線程都有自己獨(dú)立的線程上下文,包括一個(gè)唯一的整數(shù)線程ID,棧、棧指針、程序計(jì)數(shù)器、通用目的寄存器和條件碼。
- 寄存器是從不共享的,而虛擬存儲(chǔ)器總是共享的。
- 各自獨(dú)立的線程棧被保存在虛擬地址空間的棧區(qū)域中,并且通常是被相應(yīng)的線程獨(dú)立地訪問的。
將變量映射到存儲(chǔ)器
- 全局變量:定義在函數(shù)之外的變量
- 本地自動(dòng)變量:定義在函數(shù)內(nèi)部但是沒有static屬性的變量。
- 本地靜態(tài)變量:定義在函數(shù)內(nèi)部并有static屬性的變量。
共享變量
當(dāng)且僅當(dāng)變量的一個(gè)實(shí)例被一個(gè)以上的線程引用時(shí),就說(shuō)變量是共享的。
12.5用信號(hào)量同步線程
共享變量的同時(shí)引入了同步錯(cuò)誤,即沒有辦法預(yù)測(cè)操作系統(tǒng)是否為線程選擇一個(gè)正確的順序。
進(jìn)度圖
將n個(gè)并發(fā)線程的執(zhí)行模型化為一條n維笛卡爾空間中的軌跡線,將指令模型化為從一種狀態(tài)到另一種狀態(tài)的轉(zhuǎn)換。
信號(hào)量
- P(s):如果s是非零的,那么P將s減一,并且立即返回。如果s為零,那么就掛起這個(gè)線程,直到s變?yōu)榉橇恪?/li>
- V(s):將s加一,如果有任何線程阻塞在P操作等待s變?yōu)榉橇?#xff0c;那么V操作會(huì)重啟線程中的一個(gè),然后該線程將s減一,完成他的P操作。
信號(hào)量不變性:一個(gè)正確初始化了的信號(hào)量有一個(gè)負(fù)值。
信號(hào)量操作函數(shù):
int sem_init(sem_t *sem,0,unsigned int value);//將信號(hào)量初始化為value int sem_wait(sem_t *s);//P(s) int sem_post(sem_t *s);//V(s)使用信號(hào)量來(lái)實(shí)現(xiàn)互斥
二元信號(hào)量(互斥鎖):將每個(gè)共享變量與一個(gè)信號(hào)量s聯(lián)系起來(lái),然后用P(s)(加鎖)和V(s)(解鎖)操作將相應(yīng)的臨界區(qū)包圍起來(lái)。
禁止區(qū):s<0,因?yàn)樾盘?hào)量的不變性,沒有實(shí)際可行的軌跡線能夠直接接觸不安全區(qū)的部分
12.6 使用線程來(lái)提高并行性
并行程序的加速比通常定義為:
其中,p為處理器核的數(shù)量,T為在p個(gè)核上的運(yùn)行時(shí)間。
12.7 其他并發(fā)問題
線程安全
定義四個(gè)(不相交的)線程不安全函數(shù)類:
- 不保護(hù)共享變量的函數(shù)。
- 保持跨越多個(gè)調(diào)用狀態(tài)的函數(shù)。
- 返回指向靜態(tài)變量指針的函數(shù)。
- 調(diào)用線程不安全函數(shù)的函數(shù)。
競(jìng)爭(zhēng)
當(dāng)一個(gè)程序的正確性依賴于一個(gè)線程要在另一個(gè)線程到達(dá)y點(diǎn)之前到達(dá)他的控制流x點(diǎn)時(shí),就會(huì)發(fā)生競(jìng)爭(zhēng)。
為消除競(jìng)爭(zhēng),我么可以動(dòng)態(tài)地為每個(gè)整數(shù)ID分配一個(gè)獨(dú)立的塊,并且傳遞給線程例程一個(gè)指向這個(gè)塊的指針。
死鎖
死鎖:一組線程被阻塞了,等待一個(gè)永遠(yuǎn)也不會(huì)為真的條件。
- 程序員使用P和V操作順序不當(dāng),以至于兩個(gè)信號(hào)量的禁止區(qū)域重疊。
- 重疊的禁止區(qū)域引起了一組稱為死鎖區(qū)域的狀態(tài)。
- 死鎖是一個(gè)相當(dāng)難的問題,因?yàn)樗遣豢深A(yù)測(cè)的。
互斥鎖加鎖順序規(guī)則:如果對(duì)于程序中每對(duì)互斥鎖(s,t),給所有的鎖分配一個(gè)全序,每個(gè)線程按照這個(gè)順序來(lái)請(qǐng)求鎖,并且按照逆序來(lái)釋放,這個(gè)程序就是無(wú)死鎖的。
參考資料
1.《深入理解計(jì)算機(jī)系統(tǒng)》
2.《計(jì)算機(jī)操作系統(tǒng)》
轉(zhuǎn)載于:https://www.cnblogs.com/July0207/p/5023779.html
總結(jié)
以上是生活随笔為你收集整理的20135203齐岳 信息安全系统设计基础第十三周学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【linux】多线程编程(c语言编程)
- 下一篇: JPA学习(6)JPQL