前面的文章介紹了 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...