使用者級執行緒

2021-10-24 22:15:38 字數 2055 閱讀 6982

比如:

還有乙個問題,為什麼瀏覽器向伺服器請求資料的程式是乙個程序,而不是多個?瀏覽器接受伺服器的資料肯定都是儲存在乙個緩衝區裡面的,並且這個緩衝區是共享的,如果是多個程序,那麼肯定有多個對映表,也就是說如果程式裡面儲存資料的位址是連續的,經過不同的對映表之後,就會分布在記憶體的不同區域,這樣肯定沒有在一塊地方好處理呀。

上面這個例子就牽涉到執行緒(使用者級執行緒)的切換,也可以看出執行緒並不是乙個無意義的概念,而是有實際作用的。

下面說一下執行緒之間到底是如何切換的,其實主要是切過去之後還要能夠切回來。

執行緒一

100:a

()200:b(

)void

yield1()

執行緒二

300:c

()400:d(

)void

yield2()

位址

棧0x01000004

0x01000008

0x0100000c

2040x01000010

104現在執行到了線程二,計畫是在d函式裡面通過yield2跳到執行緒一的204這個位址,完成執行緒的切換。呼叫c函式,同時將304這個位址壓棧,跳到d函式裡面執行,在d函式裡面呼叫yield2,同時將404壓棧。

目前棧裡面的資料應該是:位址棧

0x01000004

4040x01000008

3040x0100000c

2040x01000010

104跳到204之後,接著執行b函式剩下的內容,執行完內容之後,函式bret彈棧,此時棧頂的位址是404,b函式應該是返回到104處,而不是404處;這裡就出現了問題。怎麼處理?

處理方法是使用2個棧,在不同的執行緒裡面使用不同的棧。在執行緒一中使用棧一執行緒二中使用棧二。這是乙個偉大的發明。

重新執行一下上面那個程式,從a函式開始執行,在b函式裡面呼叫yield1進入執行緒二的c函式之後,執行緒一對應的棧一中的內容應該是:位址棧

0x01000004

0x01000008

0x0100000c

2040x01000010

104執行到d函式的yield2之後,執行緒二對應的棧二的內容應該是:位址棧

0x02000004

0x02000008

0x0200000c

3040x02000010

404在yield2裡面做的第一件事就應該是切換棧,如何切換?肯定需要乙個資料結構將原來棧一的位址儲存起來,這個資料結構就是tcb(thread control block ) ;當前棧的棧頂位址是存放在cpu裡面的esp暫存器裡面的, 因此只需要改變esp的值就可以切換棧了。

void

yield2()

jmp到204之後,執行完b函式剩下的**之後執行b函式彈棧,這時棧頂是204,也就是又跳到204去了,顯然有問題,但是比前面已經好很多了,因為不會跳到另外乙個執行緒裡去。那現在為什麼會這樣呢?原因是yield2()直接跳到204之後,而沒有將棧中的204彈出去,如果yield2跳到204這個位置,同時將棧中的204彈出去就好了。其實這個可以實現,修改

yield2如下:

void

yield2()

沒錯,就是將jmp 204去掉就可以了,利用yield2的彈棧跳到204位址處, 執行完b函式之後, 通過b函式彈棧到104處,完美。

使用者級執行緒和核心級執行緒

根據在使用者空間還是在核心實現多執行緒機制,執行緒又被分為使用者級執行緒 user level thread 和核心級執行緒 kernel level thread 有關執行緒的所有管理工作都有在使用者級實現的執行緒庫來支援。使用者級執行緒庫是用於使用者級執行緒管理的例程包,支援執行緒的建立 終止,...

使用者級執行緒和核心級執行緒

執行緒有3種實現模型 使用者級或應用程式級執行緒 核心級執行緒 使用者級和核心級混合執行緒 圖6 1顯示了3種執行緒實現模型。圖6 1 a 顯示了使用者級執行緒,圖6 1 b 顯示了核心級執行緒,圖6 1 c 則顯示了使用者執行緒和核心執行緒的混合。這些實現之間的較大的區別之一就是它們的模式以及要指...

使用者級執行緒和核心級執行緒

6.1.1 使用者級執行緒和核心級執行緒 執行緒有3種實現模型 使用者級或應用程式級執行緒 核心級執行緒 使用者級和核心級混合執行緒 圖6 1顯示了3種執行緒實現模型。圖6 1 a 顯示了使用者級執行緒,圖6 1 b 顯示了核心級執行緒,圖6 1 c 則顯示了使用者執行緒和核心執行緒的混合。這些實現...