IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques, systèmes et outils C Discussion :

Sémaphores pour la synchro de processus


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut Sémaphores pour la synchro de processus
    Bonjour,

    J'ai un petit souci sur un projet en cours...

    En fait, j'ai plusieurs processus en exécution.
    J'ai la possibilité d'établir une communication entre un premier processus (admin) et un autre processus.
    Pour ce faire, soit l'admin envoie un signal au processus concerné, soit le processus concerné envoie un signal à l'admin pour demander une communication.

    Une fois la communication établie (qui se fait via file de messages), l'admin est considéré comme occupé, et si un autre processus demande une communication, il doit attendre 5 secondes et continuer son exécution jusqu'à ce que l'admin soit libre.

    Donc :
    Du côté admin, rien de spécial, il envoie et reçoit les messages par la file de messages.

    En revanche, du côté de l'autre processus, lors du début de l'appel, je décrémente un sémaphore (qui a été initialisé à 1 par un autre processus). Donc, si un deuxième processus demande une communication, il ne parvient pas à décrémenter le sémaphore, vu qu'il est déjà à 0. Et c'est là que ça coince... J'aimerais que ce deuxième processus continue son exécution jusqu'à ce que l'admin soit à nouveau libre.

    Voici donc le code que j'ai dans l'autre processus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        sembuf op;
        op.sem_num = 0;
        op.sem_op = -1;
        op.sem_flg = 0;
     
        alarm(5);
        if(!semop(idSem, &op, 1))
        {
            alarm(0);
     
            appel();    //Appel vers l'admin
        }
     
        op.sem_op = +1;
        semop(idSem, &op, 1);
    ce code se trouve dans une fonction handler, car l'appel est lancé via un signal. A la fin de la fonction handler se trouve un longjmp, afin de retourner à l'exécution du processus avant l'appel.

    Je pense que je n'ai pas trop compris l'utilisation de alarm()...

    En effet, avec le code ci-dessus, si un deuxième processus demande une communication, il s'arrête complètement pendant 5 secondes, et ensuite est terminé, et j'ai un message alarm qui est affiché dans le terminal du processus...

    Comment puis-je faire ?

    Merci beaucoup !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Bonjour,

    Tu peux passer des flags à semop, et notamment IPC_NOWAIT pour faire un appel non bloquant. Dans ce cas, en cas d'échec, semop renverra « -1 » et errno contiendra EAGAIN.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    Je me suis finalement arrangé un peu différemment...
    Je n'utilise plus le alarm()...

    Par contre, j'ai un autre petit problème...
    Je lance un processus. Ensuite, je demande une communication à l'admin. Je fais ça via un SIGINT (ctrl-c) envoyé au processus demandeur. L'admin accepte la communication. La communication se fait sans soucis, et ensuite, le processus demandeur reprend son exécution normale. Ensuite, si je renvoie une seconde fois le SIGINT (toujours avec ctrl-c), le processus l'ignore totalement...

    Le champ sa_flags de la structure sigaction que j'utilise pour armer le signal (via sigaction()) est initialisé à 0 au début du processus. Donc, en principe, le processus ne devrait pas ignorer un second signal...

    Une idée ?

    Merci

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Est-ce que tu utilises toujours longjmp() pour quitter le handler de ton signal et d'une manière générale, pourquoi fais-tu cela ?

    Il faut laisser la fonction du gestionnaire aller jusqu'à son terme et ton programme reprendra naturellement là où il a été interrompu, et les flags des différents signaux seront réarmés normalement par le système.

    En principe, sigaction() ne restaure pas le handler par défaut après appel sans le flag idoine, comme tu le précises. Par contre, signal() « peut » le faire. En pratique, SysV le fait mais pas BSD.

    Par contre, par défaut, Ctrl-C et SIGINT interrompent le programme et y mettent fin. Donc, ignorer ce signal n'est absolument pas le comportement par défaut. Ce qu'il se passe, c'est qu'un signal est automatiquement masqué lorsque l'on l'a reçu et qu'on se trouve dans son gestionnaire, pour éviter la réentrance. Comme chaque signal est indiqué par son propre flag, tu peux considérer que tu peux avoir exactement un signal de chaque type en attente, qui peut même être reçu pendant que tu traites le précédent, mais pas plus. Mais comme tu sors avec longjmp(), le système ne peut pas savoir qu'on est sorti du gestionnaire et le signal est toujours masqué.

    Il existe sigsetjmp() et siglompjmp() pour tenir compte de ce cas, mais ces appels sont définis par POSIX uniquement, là où setjmp() et longjmp() sont définis par la norme C. Mais dans tous les cas, tu ne devrais pas avoir à recourir à ces appels en temps normal.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    Bonjour.

    Oui, en effet, j'utilisais le longjmp() pour quitter le handler du signal.

    J'ai utilisé le longjmp à la base, parce que je devais pouvoir sortir du handler à des endroits différents dans le code.
    J'ai d'ailleurs, dans le cas de l'admin, des variables globales qui sont modifiées par la fonction handler. C'est pour ça que, avant d'y entrer, je sauvegardais l'environnement, afin de conserver l'état de la variable, et de la retrouver en bon état au retour du handler.
    Donc, dans le cas de l'admin, le longjmp() a été remplacé par un siglongjmp(), et dans le cas des autres processus, j'ai remplacé le longjmp() que j'utilisais pour sortir du handler par un return.

    Dans le cadre du cours concerné, on m'a d'ailleurs parlé de siglongjmp(), et non de longjmp(), et je ne connaissais pas la différence entre les deux...

    Je sais que SIGINT est en principe là pour interrompre le processus, mais justement, il m'a été demandé, pour ce projet, d'en modifier le comportement.

    Maintenant, à priori, tout fonctionne correctement

    Merci Obsidian pour tes explications, qui m'ont (une fois de plus) bien aidé

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Citation Envoyé par jerrypeeren Voir le message
    Bonjour.

    Oui, en effet, j'utilisais le longjmp() pour quitter le handler du signal. J'ai utilisé le longjmp à la base, parce que je devais pouvoir sortir du handler à des endroits différents dans le code.
    Il faut néanmoins comprendre que c'est quasiment la même chose qu'un goto. Certes, l'environnement initial sera restauré, et donc la pile ramenée là où il faut, mais à chaque fois tu casses le déroulement du programme… à un endroit par nature indéfini ! Si tu te trouves dans une boucle, par exemple, il peut être nécessaire qu'elle se finisse.

    Les jumps sont intéressants principalement pour rattraper une erreur « irrécupérable », dans laquelle on préfère ramener le programme soit au début, soit à un point considéré comme sûr et abandonner le reste, plutôt que de laisser planter le tout.

    Dans les autres situations, ton programme va devenir ingérable à court terme. Si tu n'utilises les signaux que comme une sorte d'interruption logicielle, alors ton programme est censé rester dans le cadre d'un fonctionnement normal. Il vaut mieux alors tâcher de quitter le plus vite possible le gestionnaire et d'influer le moins possible sur l'environnement, pour laisser ensuite le programme normal prendre une décision. Le mieux consiste à faire une boucle principale qui, à chaque tour, décide de faire telle ou telle action en fonction des informations dont elle dispose, et faire en sorte que le gestionnaire ne fasse que modifier des flags permettant ensuite de prendre ces décisions en conséquence. Ça devient même critique lorsque tu utilises des threads.

    J'ai d'ailleurs, dans le cas de l'admin, des variables globales qui sont modifiées par la fonction handler. C'est pour ça que, avant d'y entrer, je sauvegardais l'environnement, afin de conserver l'état de la variable, et de la retrouver en bon état au retour du handler.
    Même chose : les variables globales sont à éviter autant que possible même dans le cas où elles sont justifiées, alors pourquoi, dans le cas présent, utilises-tu des variables globales si ce n'est pas pour communiquer entre le handler et le programme principal ?

    Donc, dans le cas de l'admin, le longjmp() a été remplacé par un siglongjmp(), et dans le cas des autres processus, j'ai remplacé le longjmp() que j'utilisais pour sortir du handler par un return.
    En principe, tu ne devrais pas en avoir besoin du tout.

    Merci Obsidian pour tes explications, qui m'ont (une fois de plus) bien aidé
    À ton service.
    Bon courage.

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    Je vais probablement tenter de corriger ces petites "erreurs" après ma session d'examens (je parle des jumps). La présentation étant demain, je n'aurai pas le temps de corriger ça avant...

    Sinon, pour les variables globales, il nous a été conseillé, lors des cours théoriques, de déclarer une variable en global si cette variable est utilisée dans toutes les fonctions du fichier source (ou presque). Toutefois, il n'a jamais été question des raisons pour lesquelles il faudrait éviter de telles variables.

    Je ne sais pas si c'est un oubli de la part des professeurs, ou si c'est volontaire...

    Un cours sur les threads commencera après cette session d'examens, et je suppose que nous nous heurterons assez rapidement au problème des variables globales.

    A nouveau, merci pour tes conseils avisés, je tâcherai d'en tenir compte lors du développement de mes projets futurs

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Citation Envoyé par jerrypeeren Voir le message
    Sinon, pour les variables globales, il nous a été conseillé, lors des cours théoriques, de déclarer une variable en global si cette variable est utilisée dans toutes les fonctions du fichier source (ou presque). Toutefois, il n'a jamais été question des raisons pour lesquelles il faudrait éviter de telles variables.

    Je ne sais pas si c'est un oubli de la part des professeurs, ou si c'est volontaire...
    Les variables globales viennent très rapidement à l'esprit, aussi bien sémantiquement que techniquement et il est normal de voir qu'elles existent. Toutefois, j'espère que cette omission sera rapidement réparée dans les prochains cours, sinon ce serait une grosse lacune dans l'apprentissage.

    Une fois que les raisons exposées ci-dessus sont bien comprises, tu peux les utiliser si tu écris un projet qui t'est propre et que tu n'as pas l'intention d'étendre, ou si tu ne peux pas faire autrement car tu travailles en environnement imposé (par exemple, avec une bibliothèque pas propre), mais les cas où tu peux les utiliser sans qu'elles te causent d'ennuis et surtout sans risquer de compromettre l'évolution ultérieure de ton programme (c'est à la fois l'enjeu le plus important et le plus difficile à cerner au départ) sont tellement limités qu'ils vaut mieux prendre d'emblée l'habitude de faire sans.

    Évidemment, tout comme les gotos, l'idée étant de suivre dès le départ la bonne voie et pas de choisir une solution encore plus sale simplement pour le principe de les éviter.

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    C'est noté.

    Avec la pratique viendra la compréhension
    Des projets, j'en aurai encore pas mal d'ici la fin de l'année scolaire (fin juin dans mon cas), donc, j'aurai encore bien des occasions de mettre en pratique ces conseils

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme de VS2008 pour debugger le bon processus
    Par arasium dans le forum Visual Studio
    Réponses: 0
    Dernier message: 20/11/2008, 15h59
  2. Réponses: 2
    Dernier message: 04/08/2008, 17h44
  3. API pour savoir si un processus est en train de marcher
    Par andrianiaina dans le forum Windows
    Réponses: 2
    Dernier message: 17/10/2006, 16h23
  4. API pour savoir si un processus est en train de marcher
    Par andrianiaina dans le forum Windows
    Réponses: 5
    Dernier message: 16/10/2006, 16h57
  5. Quels composants pour une synchro avec palm ?
    Par tipiweb dans le forum Composants VCL
    Réponses: 2
    Dernier message: 07/11/2005, 15h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo