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

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

www. gin images lee cpu -o events 其他 p s

目錄
  • 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),睡眠(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

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