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 前言
問題:協程如何定義? 排程器如何定義?
先來一道設計題:
設計一個協程的執行體R與執行體排程器S的結構體
1. 執行體R:包含執行狀態{就緒,睡眠,等待},執行體回撥函式,回撥引數,棧指標,棧大小,當前執行體
2. 排程器S:包含執行集合{就緒,睡眠,等待}
這道設計題拆分兩個個問題,一個執行體如何高效地在多種狀態集合更換。排程器與執行體的功能界限。
7.1 執行體如何高效地在多種狀態集合更換
新建立的協程,建立完成後,加入到就緒集合,等待排程器的排程;協程在執行完成後,進行IO操作,此時IO並未準備好,進入等待狀態集合;IO準備就緒,協程開始執行,後續進行sleep操作,此時進入到睡眠狀態集合。
就緒(ready),睡眠(sleep),等待(wait)集合該採用如何資料結構來儲存?
就緒(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