web-dev-qa-db-fra.com

Un processus peut-il être gelé temporairement sous Linux?

Je me demandais s'il y avait un moyen de geler un processus pendant un certain temps?

Ce que je veux dire, c'est que: est-il possible pour une application (fonctionnant probablement en tant que root) de suspendre l'exécution d'un autre processus en cours d'exécution (tout processus, à la fois l'interface graphique et la ligne de commande), puis de le reprendre plus tard? En d'autres termes, je ne souhaite pas que certains processus soient planifiés par le planificateur Linux pendant un certain temps.

52
Pal Szasz

Voir ici

Il y a deux signaux pouvant suspendre l'exécution d'un processus. On est "gracieux", et on est "force".

Le "gracieux" est SIGTSTP et son but est de demander "gentiment" au processus, s'il le souhaite, de suspendre l'exécution jusqu'à ce qu'il reçoive un SIGCONT. Dans le cas de SIGTSTP, le processus peut ignorer SIGTSTP et continuer à exécuter de toute façon. Cela nécessite donc la coopération d'un programme conçu pour gérer SIGTSTP.

Le "forceful" est SIGSTOP et son but est de suspendre tous les threads de l'espace utilisateur associés à ce processus. Il est tout aussi impossible pour le processus d'ignorer SIGSTOP que pour lui d'ignorer SIGKILL (ce dernier tue le processus avec force).

Pour envoyer un signal arbitraire, y compris ceux mentionnés ici, vous pouvez utiliser des programmes tels que kill, killall ou pkill; ou utilisez l'appel système kill(2). Consultez les pages de manuel de votre système d'exploitation pour connaître les détails relatifs à la plate-forme/architecture/version et les errata concernant ce qui précède. Notez que le mot "tuer" dans toutes ces commandes et l'appel système est un mauvais nom impropre. Ces commandes sont non conçues exclusivement pour mettre fin aux processus. Ils peuvent le faire en envoyant certains signaux; mais les signaux peuvent également être utilisés pour des fonctionnalités autres que la fin d'un processus. Par exemple, SIGSTOP suspend uniquement le processus et il ne s'agit que d'un des nombreux signaux pouvant être envoyés de cette façon.

Pour ajouter une condition de reprise automatique du processus une fois le délai écoulé, vous devez utiliser une sorte de processus de surveillance qui reste en cours d'exécution et définit un minuteur afin de réactiver le processus de surveillance, qui appelle ensuite à nouveau kill(2). et envoie le signal SIGCONT au processus arrêté, afin de demander au noyau de reprendre l'exécution. Notez que Linux possède plusieurs mécanismes de synchronisation avec différents degrés de précision et de précision. de plus, si votre système est très occupé, votre processus de surveillance risque de ne pas être réveillé bien après l'expiration de son délai, ce qui risque de retarder le réveil.

Si vous comptez sur une précision très précise de la suspension et de la reprise du processus suspendu, vous devrez peut-être exécuter votre programme de surveillance avec des autorisations en temps réel (voir cette page de manuel sur sched_setscheduler(2) pour obtenir des informations sur la manière de rendre votre processus en temps réel). Vous pouvez également utiliser les timers haute résolution, une fonctionnalité du noyau Linux (disponible uniquement si votre matériel les prend en charge), en combinaison avec la planification en temps réel, pour obtenir très précis, précision au-dessous de la milliseconde sur la synchronisation, puis réveil et envoyer le signal pour reprendre le processus surveillé très rapidement.

Vous n'avez pas indiqué les technologies que vous êtes prêt à utiliser pour mettre cela en œuvre. Au minimum, vous aurez besoin d'au moins script bash, bien que vous ne puissiez pas obtenir un minutage très précis de cette façon. Voici un "script" bash (non testé, donc soyez prudent) qui est juste une preuve de concept de votre requête. Si vous avez besoin d'un timing précis, vous devrez écrire un programme, probablement en C/C++ ou dans un autre langage natif, et utiliser la planification en temps réel et les horloges hr.

#!/bin/bash
#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
kill -SIGSTOP ${THEPID}
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"

Notez que le script se terminera et que le script de contrôle se terminera, mais en raison de screen contrôlant le processus de contrôle, il continuera à s'exécuter en arrière-plan pendant 10 secondes (en fonction de l'argument transmis à sleep), puis réveillera et poursuivra le processus enfant. . Mais ce sera longtemps après la fin du script de contrôle. Si vous souhaitez attendre que le temps s'écoule de manière synchrone, omettez simplement le deuxième appel à screen et codez en dur les actions sleep et kill dans le script de contrôle.

Vous pouvez tester que le processus est effectivement suspendu en exécutant

screen -rS child

après avoir démarré ce script. Vous ne verrez rien sur la console. Ensuite, une fois le délai écoulé (10 secondes), votre écran sera inondé de données base64 (caractères aléatoires de 0 à 9 et de A à F). Appuyez sur Ctrl + C pour quitter.

80
allquixotic

Oui, vous pouvez le faire en envoyant un signal STOP à un processus pour le suspendre, puis un CONT pour continuer.

usage:

kill -STOP <pid>

kill -CONT <pid>
13
user8228

Si vous avez une définition assez souple de "geler", vous pouvez vérifier la commande renice.

Renice vous permet de modifier la priorité de planification des processus en cours d'exécution.

Le processus normal valeur Nice est 0. L'augmentation de la valeur Nice rend le processus plus agréable, comme dans "Pourquoi ne pas y aller en premier". Bien que la diminution de la valeur de Nice rende un processus moins agréable, comme dans "sortez de mon chemin, je suis pressé". La plage de valeur de Nice est comprise entre -20 et 19.

Tout le monde peut rendre ses processus plus agréables. Seul root peut rendre un processus moins agréable ou modifier la gentillesse des processus d'un autre utilisateur.

Si vous définissez une valeur de processus Nice sur 19, celle-ci ne sera exécutée que si rien d'autre ne le souhaite.

Voici un exemple exécuté sur ma boîte Linux locale.

Utilisez ps -l et regardez la colonne NI pour voir une valeur de processus de Nice.

 -> ps -l 
 FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD 
 0 S 29190 402 31146 0 75 0 - 16547 wait pts/0 bash 
 0 T 29190 1105 402 0 75 0 - 23980 pts finis/0 vim 
 0 R 29190 794 402 0 76 0 - 15874 - pts/0 ps 
 

L'exécution de renice +10 sur le processus vim entraîne son exécution avec une priorité inférieure.

 -> renice +10 -p 1105 
 1105: ancienne priorité 0, nouvelle priorité 10 
 
 -> ps -l 
 FS UID PID PPID C PRI NI ADDR SZ WCHAN ATS CMY 
 0 S 29190 402 31146 0 76 0 - 16547 wait pts/0 bash 
 0 T 29190 1105 402 0 95 10 - 23980 terminer pts/0 vim 
 0 R 29190 1998 402 0 78 0 - 15874 - pts/0 ps 
 

En supposant que vous puissiez utiliser "freeze" pour signifier "ne déranger personne d'autre sur le système", vous pouvez écrire quelque chose comme:

 renice 20 -p & ltpid of interest> 
 sommeil & certain temps> 
 renice 0 -p & ltpid of interest> 

(n'oubliez pas de l'exécuter en tant que root).


notez que j’ai pris quelques libertés avec la sortie ps -l ci-dessus pour que les colonnes intéressantes apparaissent bien dans les petites cases bleues :)

11
Maurice