<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 概述 最近在研究協程的實現原理,看了云風的coroutine和騰訊的開源庫libco后,原來要實現一個協程庫也沒那么難。我先來講講云風的coroutine庫。他使用的是 `uncontext`來保存程序運行上下文,進而實現協程庫,這個庫很值深入了解一番,吃透了這個庫,協程的原理也就了解了。 頭文件 ``` #include <ucontext.h> ``` `ucontext`結構體 ```c typedef struct ucontext { unsigned long int uc_flags; struct ucontext *uc_link; stack_t uc_stack; mcontext_t uc_mcontext; __sigset_t uc_sigmask; struct _libc_fpstate __fpregs_mem; } ucontext_t; ``` * `sigset_t `和 `stack_t` 定義在標準頭文件 `<signal.h>` 中 * `uc_link`字段保存當前context結束后繼續執行的context記錄; * `uc_sigmask` 記錄該context運行階段需要屏蔽的信號; * `uc_stack` 是該context運行的棧信息, * `uc_mcontext` 則保存具體的程序執行上下文——如PC值、堆棧指針、寄存器值等信息 操作`ucontext`的四個函數 ``` getcontext() : 獲取當前context setcontext() : 切換到指定context makecontext() : 設置 函數指針 和 堆棧 到對應context保存的sp和pc寄存器中,調用之前要先調用 getcontext() swapcontext() : 保存當前context,并且切換到指定context ``` ## 通過getcontext和swapcontext實現流程控制 代碼如下 ```c int main() { ucontext_t ctx, main; int done = 1; getcontext(&ctx); if (done > 5) { printf("ctx done\n"); swapcontext(&ctx, &main); //切換到指定的main } printf("done: %d\n", done++); swapcontext(&main, &ctx); //保存當前上下文`main`,并且切換到指定`ctx` printf("return 1\n"); return 1; } ``` 具體步驟如下: * 獲取當前上下文: getcontext(&ctx); * 判斷 `done>5`, * 如果為假則保存當前上下文`main`,并且切換到指定`ctx`, `swapcontext(&main, &ctx)` * 如果為真則切換上下文: `swapcontext(&ctx, &main);`, 輸出如下: ``` done: 1 done: 2 done: 3 done: 4 done: 5 ctx done return 1 ``` ## 使用`uncontet`寫一個消費者和生產者的程序 步驟如下: * 生產者,產生一個值,保存當前上下文,切換到消費者上下文 * 消費者,輸出生產者傳遞過來的值。保存消費者的當前上下文,切換到生產者 上下文切換已經做了標記,代碼如下: ```c //procus.c #include <stdlib.h> #include <stdio.h> #include <ucontext.h> #include <stddef.h> #include <sys/types.h> #define STACK_SIZE (1024*1024) struct args { int n; int send; ucontext_t* ctx; ucontext_t* main_ctx; }; void product(void *arg) { struct args* a = (struct args*)arg; a->send = 1; while (a->n<5) { printf("a->n: %d\n", a->n++); swapcontext(a->ctx, a->main_ctx); //標記1, 保存當前上下文到a->ctx, 切換到a->main_ctx, 跳轉到標記4 } a->send = 0; printf("send is 0: %d\n", a->n++); swapcontext(a->ctx, a->main_ctx); //標記2,保存當前上下文到a->ctx, 切換到a->main_ctx, 跳轉到標記4 } void customer(void *arg) { struct args* a = (struct args*)arg; while (a->send==1) { printf("n: %d\n", a->n); swapcontext(a->main_ctx, a->ctx); //標記3,保存當前上下文到a->main_ctx, 切換到a->ctx, 跳轉到標記1 } } int main() { ucontext_t ctx, main_ctx; getcontext(&ctx); struct args a; a.n = 1; a.ctx = &ctx; a.main_ctx = &main_ctx; ctx.uc_stack.ss_sp = malloc(STACK_SIZE); //分配一塊空間 ctx.uc_stack.ss_size = STACK_SIZE; ctx.uc_link = a.main_ctx; makecontext(&ctx, product, 1, &a); //指定上下文與對應的生產者函數 swapcontext(a.main_ctx, &ctx); //標記4, 保存當前上下文到a.main_ctx, 切換到ctx,跳轉到product函數 customer(&a); //消費者函數 printf("finally return\n"); return 0; } ``` 編譯,運行,輸出如下: ``` $ gcc -g -Wall -o procus procus.c $ ./procus a->n: 1 n: 2 a->n: 2 n: 3 a->n: 3 n: 4 a->n: 4 n: 5 send is 0: 5 finally return ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看