6
votes

Empêcher plusieurs instances de processus sur Linux

Quelle est la meilleure solution sur la plate-forme Linux pour le processus (application C ++) pour vérifier son instance n'est pas déjà en cours d'exécution?


0 commentaires

5 Réponses :


5
votes

Vous pouvez utiliser des fichiers et des serrures de fichier pour y accomplir, mais, ce n'est pas ce que ce n'est pas parfait et ne copie pas le problème infâme de Firefox où il refuse de commencer parfois même s'il ne fonctionne pas déjà.

Le la logique de base est: xxx

Outre la logique ci-dessus, vous devez également utiliser un deuxième fichier que vous verrouillez pour synchroniser l'accès au fichier PID (c'est-à-dire à agir comme un mutex pour le rendre sûr en termes de concurrence au niveau du processus).


5 commentaires

Ne serait-il pas plus simple d'utiliser une prise au lieu d'un fichier et d'essayer de se lier à un port prédéfini? Et, au fait, pourquoi ne puis-je pas utiliser le verrouillage du fichier sans toute la vérification du PID?


@Jack, vous pouvez le faire sans vérification PID, mais vous courez alors le risque de supposer que le programme est ouvert lorsqu'il s'est effondré et n'a pas réussi à nettoyer le fichier (penser au problème de Firefox). De plus, Rakis apporte un bon point, ce qui est que, sur Linux, vous pouvez vérifier que le PID appartient à votre programme à l'aide des données de '/ Proc' ... Il existe des moyens programmatiques de le faire plus génériquement sur des variantes UNIX ( Au moins, vous pouvez invoquer "PS" et analyser sa production, bien que je pense que des fonctions vous permettent d'invoquer directement les informations de processus).


Pour vérifier l'existence d'un processus, appelez Kill (PID, 0). Cela réussit lorsque le processus existe, échoue autrement. Méfiez-vous du processus en cours d'exécution sur une autre machine!


@Jack: En ce qui concerne I SAIT, vous pouvez utiliser le verrouillage du fichier. Comme le programme commence, effectuez une opération d'essai de verrouillage et si elle réussit alors c'est la première instance.


@Jack: omet de ne pas lier à un port prédéfini (vraisemblablement éphémère) peut échouer pour de nombreuses raisons autres qu'une autre instance du même programme en cours d'exécution.



1
votes

Une alternative associée à la solution de Michael consiste à créer un répertoire dans un emplacement connu (probablement sous / var / run ou / tmp) et utiliser le succès / l'échec de l'appel système comme mécanisme permettant d'assurer une exclusion mutuelle. Il s'agit des mêmes CV de tour d'exclusion mutuelle utilisées depuis des années, car la création d'annuaire est atomique sur la plupart des systèmes de produits de base (peut-être tous). Un fichier PID est toujours utile dans le cas où le répertoire + la création de processus PID meurt de manière inattendue et ne parvient pas à nettoyer. En outre, lorsque vous vérifiez si le répertoire existant + PID est valide, je vous suggérerais de vérifier explicitement le symbole / proc / / exe pour vérifier que cela indique votre exécutable plutôt que de supposer que Le PID n'a pas été recyclé.


0 commentaires

-1
votes

Vous pouvez utiliser un POSIX nommé SEMAPHORE pour le faire. Il est beaucoup plus sûr que d'utiliser un verrou de fichier.


2 commentaires

Comment cela traite-t-il d'un programme qui s'est écrasé sans nettoyer le sémaphore?


À partir de la page man: POSIX nommé SEMAPHORES DOIT PERSISTENCE DE NIVEAU: SI NON ENLEVÉ PAR SEM_UNLINK (), un sémaphore existera jusqu'à ce que le système soit arrêté. Crash va certainement être un problème ici.



0
votes

Pour une application de bureau, il est probablement plus réalisable de vérifier si une instance est lancée pour utilisateur actuel , de sorte que deux utilisateurs puissent avoir leurs propres instances en cours d'exécution.

Vous pouvez utiliser des bibliothèques ( libunique (gtk +) ou QTSingleApplication (qt)), ou faites-le vous-même. En plus du fichier PID mentionné précédemment, vous pouvez ouvrir une prise FIFO ou UNIX-Domain quelque part dans le répertoire de domicile de l'utilisateur. De cette façon, vous pourriez communiquer avec l'instance de fonctionnement, par exemple. Soulevez la fenêtre de l'instance d'exécution ou dire à l'instance d'exécution pour ouvrir un nouveau fichier / URI / autre.


0 commentaires

6
votes

Le moyen standard de le faire est de créer un pidfile quelque part, contenant généralement le PID de votre programme.

Vous n'avez pas besoin de mettre le PID là-bas, vous pouvez simplement mettre un verrou exclusif. Si vous l'ouvrez pour la lecture / l'écriture et le flocez-le avec Lock_ex | LOCK_NB, il échouera si le fichier est déjà verrouillé. Ceci est sans condition de course et la serrure sera automatiquement publiée si le programme se bloque.

Normalement, vous voudriez le faire par utilisateur, de sorte que le répertoire de base de l'utilisateur est un bon endroit pour mettre le fichier.

Si c'est un démon, quelque part comme / var / exécuté est meilleur.


0 commentaires