1. 程式人生 > 實用技巧 >10、使用者級執行緒:指令的切換

10、使用者級執行緒:指令的切換

為什麼先講執行緒?因為執行緒切換是隻有指令序列(PC指標)在切換,加上記憶體切換才是程序的切換。這是從簡入繁的順序 。

1、使用者級執行緒:使用者主動切換執行緒
程序 = 資源 + 指令執行序列
執行緒保留了併發的有點,避免了程序切換的代價。

指令序列在切換的時候,需要切換PCB中記錄的資訊,暫存器等。能不能不切換記憶體對映表(暫存器還是得切換的)?答案是可以的,這就是使用者級執行緒所做的事情。將資源和指令執行分開,一個資源+多個指令執行序列。
舉個例子:一個瀏覽器需要從網上下載資料,需要顯示文字,需要解壓圖片,這些不同的任務實際上都需要共享資料,沒必要將資料儲存在不同地方,所以很適合使用多執行緒設計。

使用create建立執行緒,主動呼叫yield切換執行緒。create是製造出第一次切換時應該的樣子,yield是知道切換時需要是什麼樣子。
在這裡插入圖片描述
在這裡插入圖片描述

2、yield函式:切換棧
yield函式遇到什麼問題:指令切換時,常常會將下一條指令壓棧,以便後續恢復現場。但是對於多執行緒而言,不能共用一個棧,因為跳到別的執行緒執行的時候,會汙染原來的程式棧導致無法返回正確的下一條指令。、
在這裡插入圖片描述

怎麼解決:不同執行緒用不同的指令棧TCB,一個TCB關聯一個使用者棧,TCB切換引起使用者棧切換(因為TCB中的esp記錄的是棧的位置)。Yield函式先保護現場,將esp放在當前TCB中,用Next進行排程,從下一個TCB中取出esp,切換棧。使用全域性棧指標esp

,記錄當前正在使用的棧指標,切換的時候,把當前棧指標儲存到TCB中,到時候從中恢復。
為什麼這樣解決:最關鍵的地方在於,yield為什麼不需要指定切換完之後要執行的下一條PC指令?⭐⭐⭐⭐⭐⭐
因為棧中的下一條PC指令是在呼叫yield時壓進去的,別的程序呼叫yield之後,遇到函式的 },就會自動從棧中彈出一條指令。只要我在程式的 }之前完成了棧的切換, }之後就會自動彈出之前被壓進去的下一條PC指令。根據這樣的設計,執行緒的初始化只要在執行緒的初始化棧中事先存進這個執行緒的第一條PC指令(起始地址),那麼在第一次由yield切換到這個執行緒時,yield的 }會自動將這個新執行緒中彈出這個被我們存進的第一條PC指令,開始執行新的執行緒。

在這裡插入圖片描述

3、ThreadCreate():做出兩個TCB、兩個棧、待切換到PC存在棧中
申請棧、申請TCB、將起始地址等壓入棧中、關聯TCB和棧
在這裡插入圖片描述
在這裡插入圖片描述