使用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...