1. 程式人生 > >Linux高效能網路:協程系列07-協程實現之定義

Linux高效能網路:協程系列07-協程實現之定義

目錄

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