GNU/Linux >> Tutoriels Linux >  >> Linux

Comment mmaper la pile pour l'appel système clone() sous Linux ?

Vous voudriez le drapeau MAP_ANONYMOUS pour mmap. Et le MAP_GROWSDOWN puisque vous voulez l'utiliser comme une pile.

Quelque chose comme :

void *stack = mmap(NULL,initial_stacksize,PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_GROWSDOWN|MAP_ANONYMOUS,-1,0);

Voir la page de manuel de mmap pour plus d'informations. Et rappelez-vous, le clone est un concept de bas niveau, que vous n'êtes pas censé utiliser à moins que vous n'ayez vraiment besoin de ce qu'il offre. Et il offre beaucoup de contrôle - comme définir sa propre pile - juste au cas où vous voudriez faire des trucs (comme avoir la pile accessible dans tous les processus associés). À moins que vous n'ayez de très bonnes raisons d'utiliser le clone, tenez-vous-en à fork ou pthreads.


Les piles ne sont pas, et ne peuvent jamais être, illimitées dans leur espace de croissance. Comme tout le reste, ils vivent dans l'espace d'adressage virtuel du processus, et la quantité dont ils peuvent croître est toujours limitée par la distance à la région de mémoire mappée adjacente.

Lorsque les gens parlent de la croissance dynamique de la pile, ils peuvent signifier l'une des deux choses suivantes :

  • Les pages de la pile peuvent être des pages zéro copie sur écriture, qui ne reçoivent pas de copies privées tant que la première écriture n'est pas effectuée.
  • Les parties inférieures de la région de la pile peuvent ne pas encore être réservées (et donc ne pas compter dans les frais de validation du processus, c'est-à-dire la quantité de mémoire physique/d'échange que le noyau a comptabilisée comme réservée pour le processus) jusqu'à ce qu'une page de garde soit atteinte , auquel cas le noyau valide davantage et déplace la page de garde, ou tue le processus s'il ne reste plus de mémoire à valider.

Essayer de se fier au MAP_GROWSDOWN le drapeau n'est pas fiable et dangereux car il ne peut pas vous protéger contre mmap créer un nouveau mappage juste à côté de votre pile, qui sera ensuite écrasé. (Voir http://lwn.net/Articles/294001/) Pour le thread principal, le noyau réserve automatiquement la taille de pile ulimit équivalent à espace d'adressage (pas de mémoire ) sous la pile et empêche mmap de l'attribuer. (Mais attention ! Certains noyaux corrigés par des fournisseurs défectueux désactivent ce comportement, ce qui entraîne une corruption aléatoire de la mémoire !) Pour les autres threads, vous devez simplement devoir mmap toute la plage d'espace d'adressage dont le thread pourrait avoir besoin pour la pile lors de sa création. Il n'y a pas d'autre moyen. Vous pourriez faites-en la plupart initialement non inscriptibles/non lisibles, et changez cela en cas d'erreur, mais vous auriez alors besoin de gestionnaires de signaux et cette solution n'est pas acceptable dans une implémentation de threads POSIX car elle interférerait avec les gestionnaires de signaux de l'application. (Notez que, en tant qu'extension, le noyau pourrait offre spéciale MAP_ flags pour délivrer un signal différent au lieu de SIGSEGV en cas d'accès illégal au mappage, puis l'implémentation des threads pourrait intercepter et agir sur ce signal. Mais Linux à l'heure actuelle n'a pas une telle fonctionnalité.)

Enfin, notez que le clone syscall ne prend pas d'argument de pointeur de pile car il n'en a pas besoin. L'appel système doit être effectué à partir du code assembleur, car le wrapper de l'espace utilisateur est nécessaire pour modifier le pointeur de pile dans le thread "enfant" pour pointer vers la pile souhaitée et éviter d'écrire quoi que ce soit dans la pile du parent.

En fait, clone prend un argument de pointeur de pile, car il n'est pas sûr d'attendre pour changer le pointeur de pile dans "l'enfant" après être revenu dans l'espace utilisateur. À moins que tous les signaux ne soient bloqués, un gestionnaire de signaux peut s'exécuter immédiatement sur la mauvaise pile, et sur certaines architectures, le pointeur de pile doit être valide et pointer vers une zone sûre pour écrire à tout moment.

Non seulement la modification du pointeur de pile est impossible à partir de C, mais vous ne pouvez pas non plus éviter la possibilité que le compilateur obstrue la pile du parent après l'appel système mais avant que le pointeur de pile ne soit modifié.


Linux
  1. Comment utiliser systemd-nspawn pour la récupération du système Linux

  2. Comment vérifier la version du système d'exploitation et de Linux

  3. Comment changer l'identité d'un système Linux

  4. Linux - Comment désactiver le bip système pour les utilisateurs non privilégiés ?

  5. Comment trouver l'application pour un type MIME sous Linux ?

Comment utiliser la commande fd sur le système Linux

Comment installer l'un des meilleurs moniteurs système pour le bureau Linux

Les 10 meilleurs visualiseurs de bandes dessinées pour système Linux

Les 10 meilleurs logiciels de streaming radio pour système Linux

Les 15 meilleurs émulateurs Linux pour système Windows

Les 20 meilleurs outils bioinformatiques pour le système Linux