Linux高性能網絡:協程系列07-協程實現之定義
- Linux高性能網絡:協程系列01-前言
- Linux高性能網絡:協程系列02-協程的起源
- Linux高性能網絡:協程系列03-協程的案例
- Linux高性能網絡:協程系列04-協程實現之工作原理
- Linux高性能網絡:協程系列05-協程實現之原語操作
- Linux高性能網絡:協程系列06-協程實現之切換
- Linux高性能網絡:協程系列07-協程實現之定義
- Linux高性能網絡:協程系列08-協程實現之調度器
- Linux高性能網絡:協程系列09-協程性能測試
- [Linux高性能網絡:協程系列10 待續]()
7.協程實現之定義
- 7.0 前言
- 7.1 運行體如何高效地在多種狀態集合更換
- 7.2 調度器與協程的功能界限
7.0 前言
問題:協程如何定義? 調度器如何定義?
先來一道設計題:
設計一個協程的運行體R與運行體調度器S的結構體
1. 運行體R:包含運行狀態{就緒,睡眠,等待},運行體回調函數,回調參數,棧指針,棧大小,當前運行體
2. 調度器S:包含執行集合{就緒,睡眠,等待}
這道設計題拆分兩個個問題,一個運行體如何高效地在多種狀態集合更換。調度器與運行體的功能界限。
7.1 運行體如何高效地在多種狀態集合更換
新創建的協程,創建完成後,加入到就緒集合,等待調度器的調度;協程在運行完成後,進行IO操作,此時IO並未準備好,進入等待狀態集合;IO準備就緒,協程開始運行,後續進行sleep操作,此時進入到睡眠狀態集合。
就緒(ready)集合並不沒有設置優先級的選型,所有在協程優先級一致,所以可以使用隊列來存儲就緒的協程,簡稱為就緒隊列(ready_queue)。
睡眠(sleep)集合需要按照睡眠時長進行排序,采用紅黑樹來存儲,簡稱睡眠樹(sleep_tree)紅黑樹在工程實用為<key, value>, key為睡眠時長,value為對應的協程結點。
等待(wait)集合,其功能是在等待IO準備就緒,等待IO也是有時長的,所以等待(wait)集合采用紅黑樹的來存儲,簡稱等待樹(wait_tree),此處借鑒nginx的設計。
數據結構如下圖所示:
Coroutine就是協程的相應屬性,status表示協程的運行狀態。sleep與wait兩顆紅黑樹,ready使用的隊列,比如某協程調用sleep函數,加入睡眠樹(sleep_tree),status |= S即可。比如某協程在等待樹(wait_tree)中,而IO準備就緒放入ready隊列中,只需要移出等待樹(wait_tree),狀態更改status &= ~W即可。有一個前提條件就是不管何種運行狀態的協程,都在就緒隊列中,只是同時包含有其他的運行狀態。
7.2 調度器與協程的功能界限
每一協程都需要使用的而且可能會不同屬性的,就是協程屬性。每一協程都需要的而且數據一致的,就是調度器的屬性。比如棧大小的數值,每個協程都一樣的後不做更改可以作為調度器的屬性,如果每個協程大小不一致,則可以作為協程的屬性。
用來管理所有協程的屬性,作為調度器的屬性。比如epoll用來管理每一個協程對應的IO,是需要作為調度器屬性。
按照前面幾章的描述,定義一個協程結構體需要多少域,我們描述了每一個協程有自己的上下文環境,需要保存CPU的寄存器ctx;需要有子過程的回調函數func;需要有子過程回調函數的參數 arg;需要定義自己的棧空間 stack;需要有自己棧空間的大小 stack_size;需要定義協程的創建時間 birth;需要定義協程當前的運行狀態 status;需要定當前運行狀態的結點(ready_next, wait_node, sleep_node);需要定義協程id;需要定義調度器的全局對象 sched。
協程的核心結構體如下:
typedef struct _nty_coroutine {
nty_cpu_ctx ctx;
proc_coroutine func;
void *arg;
size_t stack_size;
nty_coroutine_status status;
nty_schedule *sched;
uint64_t birth;
uint64_t id;
void *stack;
RB_ENTRY(_nty_coroutine) sleep_node;
RB_ENTRY(_nty_coroutine) wait_node;
TAILQ_ENTRY(_nty_coroutine) ready_next;
TAILQ_ENTRY(_nty_coroutine) defer_next;
} nty_coroutine;
調度器是管理所有協程運行的組件,協程與調度器的運行關系。
調度器的屬性,需要有保存CPU的寄存器上下文 ctx,可以從協程運行狀態yield到調度器運行的。從協程到調度器用yield,從調度器到協程用resume。
以下為協程的定義。
typedef struct _nty_coroutine_queue nty_coroutine_queue;
typedef struct _nty_coroutine_rbtree_sleep nty_coroutine_rbtree_sleep;
typedef struct _nty_coroutine_rbtree_wait nty_coroutine_rbtree_wait;
typedef struct _nty_schedule {
uint64_t birth;
nty_cpu_ctx ctx;
struct _nty_coroutine *curr_thread;
int page_size;
int poller_fd;
int eventfd;
struct epoll_event eventlist[NTY_CO_MAX_EVENTS];
int nevents;
int num_new_events;
nty_coroutine_queue ready;
nty_coroutine_rbtree_sleep sleeping;
nty_coroutine_rbtree_wait waiting;
} nty_schedule;
更多分享
email: [email protected]
email: [email protected]
email: [email protected]
協程技術交流群:829348971
Linux高性能網絡:協程系列07-協程實現之定義