使用 ucontext 實現使用者態執行緒 下

2021-10-19 05:33:59 字數 2610 閱讀 3937

前面的文章介紹了 ucontext 相關函式的基本作用,我們已經知道如何用 getcontext 等函式實現基本的函式 yield & resume 的操作了。下面來看看如何實現乙個簡陋的使用者態執行緒庫吧!

首先來看我們 thread 的定義:

#define stack_size 4096

typedef

struct thread thread_t;

struct thread

;

thread 的結構體是比較簡單的,下面我們來看如何建立乙個執行緒:

// 排程器的上下文

ucontext_t sched_ctx;

// 全域性可執行執行緒佇列

thread_t runq;

// 當前正在執行的執行緒

thread_t *cur_thread

// 所有 thread 的真正函式體

void

_thread_main()

void

thread_free

(thread_t *th)

thread_t *

thread_create

(void*(

*fn)

(void*)

,void

*arg)

thread_create 中沒什麼新鮮的東西,但是仍然有兩點值得我們注意

所有執行緒的 ucontext.uc_link 設定為了 sched_ctx,這個上下文代表的是排程器的上下文,在乙個執行緒退出後,會回到排程器例程

makecontext 中,指定的是 _thread_main 作為真正的執行緒執行入口,我們可以在裡面做一些必要的初始化、或者善後工作,儘管它現在很簡陋

建立執行緒後我們把它新增到了全域性的可執行執行緒佇列中,這個佇列就是乙個簡單的雙向鍊錶

乙個執行緒庫中,最重要的模組之一便是排程器了。我們的排程器可以說非常簡陋:

// 讓出 cpu 讓排程器可以排程其他執行緒,儲存當前執行緒的上下文並且恢復排程器的上下文

void

yield()

// 恢復某個執行緒的執行,僅會被排程器使用,儲存排程器的上下文並且恢復對應執行緒的上下文

void

resume

(thread_t *th)

// 排程器

void

schedule()

// 找到了乙個可執行執行緒,設定為當前執行緒

cur_thread = th;

// 恢復執行緒之前儲存的上下文

resume

(th)

;// 如果協程函式執行結束,那麼**其資源

if(th->done)

th = next;

}// 退出排程器

}

yield 和 resume 可以說是實現使用者態執行緒的兩個核心函式,需要注意:

到這裡,其實我們的小執行緒庫就基本開發好了,下面讓我們來看一下如何使用它:

void*fn

(void

*arg)

return

null;}

#define thread_num 2

intmain()

schedule()

;printf

("all threads done\n");

}/*輸出:thread[1] do some cpu work

thread[1] need to wait on a lock or io event

thread[0] do some cpu work

thread[0] need to wait on a lock or io event

thread[1] ready again

thread[1] do some cpu work

thread[1] need to wait on a lock or io event

thread[0] ready again

thread[0] do some cpu work

thread[0] need to wait on a lock or io event

thread[1] ready again

thread[1] do some cpu work

thread[1] need to wait on a lock or io event

thread[0] ready again

thread[0] do some cpu work

thread[0] need to wait on a lock or io event

thread[1] ready again

thread[0] ready again

all threads done

*/

可以看到,兩個執行緒的輸出互相穿插,兩個執行緒都會執行一會非阻塞的 cpu 計算,然後就執行一些阻塞的 io 操作或者鎖操作等。當執行阻塞操作的時候,就暫停當前執行緒,切換到排程器去執行新的可執行執行緒。

儘管及其簡陋,但是我們的小執行緒庫已經初具雛形,到這裡想必大家對於如何利用 ucontext 實現乙個使用者態執行緒已經心裡有數了吧。

實戰 C語言實現使用者態執行緒

會帶你循序漸近的掌握下面的知識點 為什麼使用 32 位系統?因為方便初學者學習,能更快速的掌握原理。最終我們實驗完成的效果應該是下面這個樣子 圖1 使用者態執行緒執行示例 需要注意的是,上面的 並沒有使用作業系統為我們提供的pthread系列函式,thread create和thread join函...

使用tornado實現使用者認證

關於使用者的登入狀態,一部分的應用程式是採用session實現的。http是乙個無狀態協議,使用者的每次請求都是相互獨立的,http本身意識不到使用者是否登入。很多web框架選擇將session存放在cookies中,本節我們也是這樣實現 import tornado.ioloop import t...

opensips中使用mysql實現使用者認證

ubuntu中 使用mysql實現 opensips使用者認證 1 mysql支援 1.1 mysql模組支援 預設安裝時,不包含mysql模組。opensipsctlrc檔案中包含了資料庫配置的資訊,要想讓opensips支援mysql資料庫,在編譯安裝的時候 就要支援mysql模組。方法如下 1...