使用ucontext 來手動切換上下文

2021-08-22 13:41:54 字數 2645 閱讀 9934

使用ucontext.h裡面的函式和資料結構,可以讓使用者實現手動來切換函式的執行流,**libtask-輕量級協程庫**就是使用ucontext.h來實現協程的。
主要的資料結構是:ucontext_t:
typedef

struct ucontext ucontext_t;

其中有幾個成員是我們需要注意的:

成員說明

uc_link

這個成員指向了當前函式返回之後繼續執行的上下文

uc_sigmask

這個成員是跟訊號相關的

uc_stack

這個成員是當前上下文所使用的棧

uc_mcontext

這個成員包括了一些暫存器變數

warning:如果uc_link指標為null,那麼當該上下文結束之後,執行該上下文的執行緒會退出

我們主要會使用下面4個函式來對上下文進行操作:

成員說明

getcontext(ucontext_t *ucp)

獲取當前執行的上下文

setcontext(const ucontext_t *ucp)

恢復ucp指向的上下文

makecontext(ucontext_t *ucp, void(*func)(void), int argc, …)

設定該上下文到函式func,並且設定上下文開始執行時的引數和引數個數

swapcontext(ucontext_t *oucp, const ucontext_t *ucp)

切換到ucp上下文執行,並且把當前上下文儲存在oucp裡面

所以一般我們的呼叫順序是:

1.getcontext:先得到當前的上下文。

2.makecontext:設定該上下文到函式func。

3.setcontext or swapcontext:切換到指定的上下文開始執行。

#include 

#include

#include

#include

#include

#include

static ucontext_t maincontext, sumcontext, multicontext;

#define stacksize 1 << 13

int add(int a, int b)

printf("the add result is : %d.\n", a + b);

return a + b;

}int mul(int a, int b)

printf("the multi result is : %d.\n", a * b);

return a * b;

}int main(int argc, char **argv)

sumcontext.uc_stack.ss_sp = firststack;

sumcontext.uc_stack.ss_size = stacksize;

sumcontext.uc_link = &maincontext;

if ((n = getcontext(&multicontext)) < 0)

multicontext.uc_stack.ss_sp = secondstack;

multicontext.uc_stack.ss_size = stacksize;

multicontext.uc_link = &sumcontext;

makecontext(&sumcontext, (void(*)())add, 2, 4, 5);

makecontext(&multicontext, (void(*)())mul, 2, 3, 4);

if ((n = swapcontext(&maincontext, &multicontext)) < 0)

return

0;}

上面執行完之後的結果是:

上面的**會如下執行:

1.主函式先執行,並且設定sumcontext, multicontext兩個上下文的棧和上下文的開始執行位置。

2.暫停主函式的執行,把主函式的上下文儲存在maincontext裡面,然後切換到addcontext去執行,因為addcontext的開始執行點為mul函式,所以會從mul函式的第一條指令開始往下執行。

3.mul函式裡面又會進行切換,切換到sumcontext上下文開始執行,並且儲存當前執行的上下文到multicontext裡面。

4.在add函式裡面再次進行切換,切換到multicontext上下文,因為在第三步的時候,已經把相關的上下文儲存在了multicontext裡面,所以切換的時候會繼續mul函式中斷之後的下一條指令開始執行。

5.multicontext返回,multicontext的uc_link欄位指向的是sumcontext,所以sumcontext繼續執行。

6.sumcontext返回,sumcontext的uc_link欄位指向的是主函式的context,所以主函式繼續執行。

7.主函式return。

使用 ucontext 實現使用者態執行緒 下

前面的文章介紹了 ucontext 相關函式的基本作用,我們已經知道如何用 getcontext 等函式實現基本的函式 yield resume 的操作了。下面來看看如何實現乙個簡陋的使用者態執行緒庫吧!首先來看我們 thread 的定義 define stack size 4096 typedef...

HA模式手動切換namenode狀態

檢視狀態 hdfs haadmin getservicestate nn1 有時候通過網頁訪問兩個namenode的http address,看到預設的主namenode狀態變成了standy,這時可以通過下面命令來實現主namenode的狀態切換成active。hdfs haadmin failo...

HA模式手動切換namenode狀態

檢視狀態 hdfs haadmin getservicestate nn1 有時候通過網頁訪問兩個namenode的http address,看到預設的主namenode狀態變成了standy,這時可以通過下面命令來實現主namenode的狀態切換成active。hdfs haadmin failo...