Setcontext - setcontext - Wikipedia
setcontext je jednou z rodiny C knihovna funkce (ostatní jsou getcontext, makecontext a swapcontext) používá kontext řízení. The setcontext
rodina umožňuje implementaci v jazyce C pro pokročilé regulační tok vzory jako iterátory, vlákna, a coutiny. Mohou být považovány za pokročilou verzi setjmp / longjmp; zatímco druhý umožňuje pouze jeden nelokální skok nahoru zásobník, setcontext
umožňuje vytvoření více družstevní vlákna kontroly, každý s vlastním zásobníkem.
Specifikace
setcontext
bylo uvedeno v POSIX.1-2001 a Single Unix Specification, verze 2, ale ne všechny Unixový operační systémy poskytnout jim. POSIX.1-2004 zastaralé tyto funkce a v POSIX.1-2008 byly odstraněny, s POSIX vlákna označeno jako možná náhrada. Cituje IEEE Std 1003.1, vydání 2004[1]:
Se začleněním normy ISO / IEC 9899: 1999 do této specifikace bylo zjištěno, že norma ISO C (článek 6.11.6) specifikuje, že použití deklarátorů funkcí s prázdnými závorkami je zastaralá funkce. Proto pomocí prototypu funkce:
prázdnota makecontext(ucontext_t *ucp, prázdnota (*func)(), int argc, ...);
využívá zastaralou vlastnost normy ISO C. Proto přísně vyhovující aplikace POSIX nemůže použít tento formulář. Proto je použití getcontext (), makecontext () a swapcontext () označeno jako zastaralé.
Ve standardu ISO C neexistuje způsob, jak specifikovat prototyp nezastaralé funkce, což naznačuje, že funkce bude volána s libovolným počtem (včetně nuly) argumentů libovolných typů (včetně celých čísel, ukazatelů na data, ukazatelů na funkce a kompozitní typy).
Definice
Funkce a přidružené typy jsou definovány v ucontext.h
Systém hlavičkový soubor. To zahrnuje ucontext_t
typ, se kterým fungují všechny čtyři funkce:
typedef struktur { ucontext_t *uc_link; sigset_t uc_sigmask; stack_t uc_stack; mcontext_t uc_mcontext; ...} ucontext_t;
uc_link
ukazuje na kontext, který bude obnoven po ukončení aktuálního kontextu, pokud byl kontext vytvořen pomocí makecontext
(sekundární kontext). uc_sigmask
slouží k uložení sady signály blokován v kontextu a uc_stack
je zásobník použitý kontextem. uc_mcontext
obchody provedení Stát, včetně všech registry a procesor vlajky, ukazatel instrukce a ukazatel zásobníku; mcontext_t
je neprůhledný typ.
Funkce jsou:
int setcontext(konst ucontext_t *ucp)
- Tato funkce přenáší řízení do kontextu v
ucp
. Provádění pokračuje od bodu, ve kterém byl kontext uloženucp
.setcontext
nevrací.
- Tato funkce přenáší řízení do kontextu v
int getcontext(ucontext_t *ucp)
- Uloží aktuální kontext do
ucp
. Tato funkce se vrací ve dvou možných případech: po počátečním volání nebo při přepnutí vlákna na kontext vucp
přessetcontext
neboswapcontext
. Thegetcontext
funkce neposkytuje a návratová hodnota k rozlišení případů (jeho návratová hodnota se používá pouze k signalizaci chyby), takže programátor musí použít explicitní proměnnou příznaku, která nesmí být proměnnou registru a musí být deklarována nestálý vyhnout se konstantní šíření nebo jiný optimalizace kompilátoru.
- Uloží aktuální kontext do
prázdnota makecontext(ucontext_t *ucp, prázdnota (*func)(), int argc, ...)
- The
makecontext
funkce nastaví alternativní vlákno kontroly vucp
, který byl dříve inicializován pomocígetcontext
. Theucp.uc_stack
člen by měl být namířen na vhodně velký zásobník; konstantaSIGSTKSZ
se běžně používá. Kdyžucp
skočil na používánísetcontext
neboswapcontext
, poprava začne v Vstupní bod na funkci, na kterou ukazujefunc
, sargc
argumenty, jak je uvedeno. Kdyžfunc
končí, je vrácena kontrolaucp.uc_link
.
- The
int swapcontext(ucontext_t *oucp, ucontext_t *ucp)
- Převádí kontrolu na
ucp
a uloží aktuální stav provádění dooucp
.
- Převádí kontrolu na
Příklad
Následující příklad ukazuje použití iterátoru setcontext
.
#zahrnout <stdio.h>#zahrnout <stdlib.h>#zahrnout <ucontext.h>/ * Tři kontexty: * (1) main_context1: Hlavní bod, do kterého se smyčka vrátí. * (2) main_context2: Hlavní bod, ke kterému bude ovládání ze smyčky * tok přepínáním kontextů. * (3) loop_context: Bod ve smyčce, do kterého se ovládá z hlavní vůle * tok přepínáním kontextů. * /ucontext_t main_context1, main_context2, loop_context;/ * Návratová hodnota iterátoru. * /nestálý int i_from_iterator;/ * Toto je funkce iterátoru. Zadává se při prvním volání na * swapcontext a smyčky od 0 do 9. Každá hodnota je uložena v i_from_iterator, * a poté swapcontext použitý k návratu do hlavní smyčky. Vytiskne se hlavní smyčka * hodnota a volá swapcontext k výměně zpět do funkce. Když konec * smyčky je dosaženo, funkce se ukončí a provedení se přepne na * kontext, na který odkazuje main_context1. * /prázdnota smyčka( ucontext_t *loop_context, ucontext_t *other_context, int *i_from_iterator){ int i; pro (i=0; i < 10; ++i) { / * Napište čítač smyčky do návratového místa iterátoru. * / *i_from_iterator = i; / * Uložit kontext smyčky (tento bod v kódu) do '' loop_context '', * a přepněte na other_context. * / swapcontext(loop_context, other_context); } / * Funkce propadá do volajícího kontextu s implicitním * '' setcontext (& loop_context-> uc_link); '' * /} int hlavní(prázdnota){ / * Zásobník pro funkci iterátoru. * / char iterator_stack[SIGSTKSZ]; / * Příznak označující, že iterátor byl dokončen. * / nestálý int iterator_finished; getcontext(&loop_context); / * Inicializuje kontext iterátoru. uc_link ukazuje na main_context1, the * přejděte na návrat, když iterátor skončí. * / loop_context.uc_link = &main_context1; loop_context.uc_stack.ss_sp = iterator_stack; loop_context.uc_stack.ss_size = velikost(iterator_stack); / * Vyplňte loop_context, aby se vytvořila počáteční smyčka swapcontext. The * (void (*) (void)) typecast je vyhnout se varování kompilátoru, ale je * není relevantní pro chování funkce. * / makecontext(&loop_context, (prázdnota (*)(prázdnota)) smyčka, 3, &loop_context, &main_context2, &i_from_iterator); / * Vymazat hotový příznak. * / iterator_finished = 0; / * Uložit aktuální kontext do main_context1. Po dokončení smyčky * řídicí tok se vrátí do tohoto bodu. * / getcontext(&main_context1); -li (!iterator_finished) { / * Nastavit iterator_finished tak, že když je předchozí getcontext * vráceno prostřednictvím uc_link, výše uvedená podmínka if je false a * iterátor není restartován. * / iterator_finished = 1; zatímco (1) { / * Uložte tento bod do main_context2 a přepněte do iterátoru. * První hovor zahájí smyčku. Následné hovory se přepnou na * swapcontext ve smyčce. * / swapcontext(&main_context2, &loop_context); printf("% d n", i_from_iterator); } } vrátit se 0;}
POZNÁMKA: tento příklad není správný[1], ale v některých případech může fungovat, jak bylo zamýšleno. Funkce makecontext
vyžaduje další parametry int
, ale příklad předá ukazatele. Příklad tedy může selhat na 64bitových počítačích (konkrétně LP64 -architektury, kde velikost(prázdnota*) > velikost(int)
). Tento problém lze vyřešit rozdělením a rekonstrukcí 64bitových hodnot, ale to zavádí výkonnostní trest.
Na architekturách, kde typy int a pointer mají stejnou velikost (např. X86-32, kde oba typy jsou 32 bitů), se můžete dostat pryč s předáváním ukazatelů jako argumentů tomakecontext () po argc. Není však zaručeno, že to bude přenosné, nedefinované podle standardů a nebude to fungovat na architekturách, kde jsou ukazatele větší než ints. Od verze 2.8 však glibc provádí určité změny
, aby to bylo povoleno na některých 64bitových architekturách (např. x86-64).
Pro kontext get a set může být užitečný menší kontext:
#zahrnout <stdio.h>#zahrnout <ucontext.h>#zahrnout <unistd.h>int hlavní(int argc, konst char *argv[]){ ucontext_t kontext; getcontext(&kontext); uvádí("Ahoj světe"); spát(1); setcontext(&kontext); vrátit se 0;}
Tím se vytvoří nekonečná smyčka, protože kontext drží počítadlo programu.
Reference
externí odkazy
- Kontexty systému V. - The Knihovna GNU C. Manuál
- Linux Programátor Manuál - Funkce knihovny : získat / nastavit aktuální kontext uživatele -
- setcontext - získat / nastavit aktuální kontext uživatele Manuální stránka FreeBSD.