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