En C, le contexte est l'état d'exécution actuel d'un programme, y compris les registres (petites zones de stockage au sein du CPU, utilisées pour stocker les données et les instructions pendant l'exécution du programme), les variables et le flux d'instructions, cruciales pour changer de tâche.
La fonction principale est de permettre le multitâche. Cela garantit que le système peut basculer efficacement entre les processus.
Le fichier contexts.c a été mis à disposition ici. C'est une démonstration du fonctionnement des contextes.
Tout en haut de ce fichier, on remarque l'import de la bibliothèque ucontext.h. Il permet de manipuler le contexte d'exécution.
Dans l'extrait ci-dessous nous voyons que 3 contextes sont créés, et ces 3 contextes auront de la mémoire allouée de la taille de STACKSIZE.
#define STACKSIZE 64 * 1024 /* tamanho de pilha das threads */ ucontext_t ContextPing, ContextPong, ContextMain;
Et peu après, les fonctions Ping et Pong qui seront exécutées dans leurs contextes respectifs :
void BodyPing(void *arg) { int i; printf("%s: inicio\n", (char *)arg); for (i = 0; i < 4; i++) { printf("%s: %d\n", (char *)arg, i); swapcontext(&ContextPing, &ContextPong); } printf("%s: fim\n", (char *)arg); swapcontext(&ContextPing, &ContextMain); } /*****************************************************/ void BodyPong(void *arg) { int i; printf("%s: inicio\n", (char *)arg); for (i = 0; i < 4; i++) { printf("%s: %d\n", (char *)arg, i); swapcontext(&ContextPong, &ContextPing); } printf("%s: fim\n", (char *)arg); swapcontext(&ContextPong, &ContextMain); } /*****************************************************/
Dans la fonction principale, malloc est utilisé pour réserver les piles, où elles sont ensuite affectées avec uc_stack.ss_sp au contexte, et swapcontext est utilisé pour basculer entre elles.
int main(int argc, char *argv[]) { char *stack; printf("main: inicio\n"); getcontext(&ContextPing); stack = malloc(STACKSIZE); if (stack) { ContextPing.uc_stack.ss_sp = stack; ContextPing.uc_stack.ss_size = STACKSIZE; ContextPing.uc_stack.ss_flags = 0; ContextPing.uc_link = 0; } else { perror("Erro na criação da pilha: "); exit(1); } makecontext(&ContextPing, (void *)(*BodyPing), 1, " Ping"); getcontext(&ContextPong); stack = malloc(STACKSIZE); if (stack) { ContextPong.uc_stack.ss_sp = stack; ContextPong.uc_stack.ss_size = STACKSIZE; ContextPong.uc_stack.ss_flags = 0; ContextPong.uc_link = 0; } else { perror("Erro na criação da pilha: "); exit(1); } makecontext(&ContextPong, (void *)(*BodyPong), 1, " Pong"); swapcontext(&ContextMain, &ContextPing); swapcontext(&ContextMain, &ContextPong); printf("main: fim\n"); exit(0); }
Sortie du programme exécuté :
main: inicio Ping: inicio Ping: 0 Pong: inicio Pong: 0 Ping: 1 Pong: 1 Ping: 2 Pong: 2 Ping: 3 Pong: 3 Ping: fim Pong: fim main: fim
Avec cela, nous pouvons voir que même en changeant les contextes, les valeurs qui "circulent" à travers la fonction sont conservées, un exemple dans ce cas est l'index for.
Vous avez peut-être remarqué qu'il existe un malloc pour le contexte Ping et Pong, mais nous voyons qu'il existe également un contexte pour main, pourquoi n'y a-t-il pas de malloc pour cela ?
ContextMain n'a pas besoin d'une pile séparée car il fonctionne sur la pile du thread principal, tandis que les contextes Ping et Pong ont leurs propres piles allouées dynamiquement.
Si je crée un contexte et ne lui alloue pas de mémoire, lorsque nous utilisons swap, il va dans la pile principale du programme.
Ce code est du professeur Maziero, trouvé dans le sous-projet développé de PingPongOS "Trocas de Contexto".
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!