48 votes

Comment fonctionnent les greenlets?

Comment sont greenlets mis en œuvre? Python utilise la pile C pour l'interprète et il en tas alloue Python pile d'images, mais au-delà, comment est-il allouer/échanger les piles, comment est-il du crochet dans l'interprète et de la fonction des mécanismes d'appel, et comment cette interagir avec C les extensions? (Toutes les bizarreries)?

Il y a quelques commentaires en haut de greenlet.c dans la source, mais ils sont un peu opaque. FWIW, je vais venir du point de vue de quelqu'un qui ne connaît pas Disponible internes, mais il est très familier avec le faible niveau des systèmes de programmation, C, les threads, les événements, les coroutines/coopérative des threads de noyau de programmation, etc.

(Certains points de données: ils n'utilisent pas ucontext.h et ils n'2x memcpy, alloc, et libre à chaque changement de contexte.)

32voto

user698585 Points 3019

Quand un programme en python fonctionne, vous avez essentiellement deux morceaux de code s'exécutant sous le capot.

Tout d'abord, le Disponible interprète le code C en cours d'exécution et à l'aide de la norme C-pile pour sauver sa pile interne-cadres. Deuxièmement, le python interprété bytecode qui n'utilise pas le C de la pile, mais utilise plutôt le tas pour sauver sa pile d'images. Un greenlet est juste norme de code python et donc se comporte de la même manière.

Maintenant, dans un typique microthreaded application, vous finiriez par avoir des milliers, sinon des millions de microthreads (greenlets) de commutation de tous sur la place. Chaque commutateur est essentiellement équivalent à un appel de fonction avec un différé de retour (façon de parler), et donc utiliser un peu de la pile. Le problème est, le C-pile de l'interprète, tôt ou tard, frapper un débordement de pile. C'est exactement ce que le greenlet vulgarisation visant à, il est conçu pour déplacer des pièces de la pile avant en arrière pour le/dans le tas afin d'éviter ce problème.

Comme vous le savez, il y a trois événements fondamentaux avec greenlets, un spawn, un interrupteur et un retour, alors, regardons ceux qui à son tour:

A) Un Spawn

Le nouvellement généré greenlet est associée à sa propre adresse de base de la pile (où nous sommes actuellement). En dehors de cela, rien de spécial ne se passe. Le code python de la nouvellement généré greenlet utilise le tas dans des conditions normales et l'interprète continue à utiliser le C-pile comme d'habitude.

B) Un Interrupteur

Lorsqu'un greenlet est passé à partir d'une commutation greenlet, la partie pertinente de la C-pile (à partir de l'adresse de base de la switchng greenlet) est copié dans le tas. Le copié C-pile est libéré et la commutation de greenlet de l'interprète précédemment enregistré pile de données est copié dans le tas pour le nouvellement libérés C-pile. Le code python de la commutation de greenlet continue à utiliser le tas dans des conditions normales. Bien sûr, le code d'extension garde la trace de tout cela (qui tas la section à laquelle greenlet et ainsi de suite).

C) Un Retour

La pile est intact et le segment de la zone de retour de la greenlet est libéré par le python garbage collector.

En gros, cela est-il, beaucoup plus de détails et d'explications peuvent être trouvées à l' (http://www.stackless.com/pipermail/stackless-dev/2004-March/000022.html) ou tout simplement en lisant le code comme indiqué dans Alex réponse.

30voto

Alex Martelli Points 330805

Si obtenir et étudier les greenlet de sources, vous verrez en haut de l' greenlet.c d'un long commentaire qui commence à la ligne 16 avec le résumé qui suit...:

Un PyGreenlet est une gamme de la pile C les adresses qui doivent être enregistrées et restauré dans une telle manière que la totalité de la gamme de la pile contient des données valides quand on passe.

et continue à la ligne 82, résumant exactement ce que vous demandez sur. Avez-vous des études de ces lignes (et les suivantes 1000+ leur mise en oeuvre;-)...? Je ne vois pas un moyen de continuer à presser ces lignes 66 vers le bas tout en le sens, ni de la valeur ajoutée dans un copier-coller ici.

Fondamentalement, vous verrez il n'y a pas de véritable "accrocher" pour parler de (C niveau de la pile est basculés "en vertu de l'interprète du nez", façon de parler), sauf pour la délicate interactions avec le fil de l'etat dans le code multithread, et la sauvegarde et la restauration d'un greenlet de l'état/de la pile est basé sur memcpy d'appels de plus certains appels à l'Python gestionnaire de mémoire à allouer/réaffecter et de l'espace libre en provenance, ou de revenir à la pile. Les trois fonctions en ligne 227-295 gérer le gros du travail, et ils sont enveloppés dans un couple C macros à 298-310 "afin de simplifier les opérations de maintenance", comme le commentaire il dit.

L'interface à travers laquelle les autres C des extensions peuvent interagir avec le greenlet extension est mis en œuvre à des lignes 956-1045, et exposée à travers la "CObject API" (via greenlet.h, bien sûr) documenté ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X