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

POSIX C Discussion :

signaux et alarmes


Sujet :

POSIX C

  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    août 2011
    Messages
    745
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 745
    Points : 374
    Points
    374
    Par défaut signaux et alarmes
    Bonjour,

    J'ai voulu tester deux trois petites choses, d'où le petit code qui va suivre.

    Or, je ne comprends pas ce qui se passe à l'exécution.
    À l'affichage, j'obtiens :

    Début du programme test.
    Moto: J'attends le départ.

    Puis, 10 secondes plus tard, le programme se bloque.

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    int START_MOTO=0;
    int START_VOITURE=0;
     
     
    void motoGo(){
    	START_MOTO=1;
    }
     
    void moto(){
    	if(START_MOTO==0){
    		printf("Moto: J'attends le départ\n");
    		pause();
    	}
    	printf("Vroum la moto démarre\n");
    }
     
    void voitureGo(){
    	START_VOITURE=1;
    }
     
    void voiture(){
    	if(START_VOITURE==0){
    		printf("Voiture: J'attends le départ\n");
                    pause();
    	}
    	printf("Zut j'ai plus d'essence !!!\n");
    }
     
    int main(){
    	pid_t pid[2];
    	int k=0;
    	printf("Début du programme test\n");
    	switch(pid[0]=fork()){
    		case -1:
    			perror("Erreur fork");
    			exit(1);
    		case 0:
    				moto();
    			break;
    		}
    		switch(pid[1]=fork()){
    		case -1:
    			perror("Erreur fork");
    			exit(1);
    		case 0:
    				voiture();
    			break;
    		}
     
    		signal(SIGUSR1,voitureGo);
    		signal(SIGALRM,motoGo);
    		kill(pid[1],SIGUSR1);
    		alarm(10);
    		for(k=0;k<2;k++){
    			wait(NULL);
    		}
    		printf("Fin du programme test\n");
    	return 0;
    }
    Dans mon idée, les deux processus devraient attendre le signal après leur création, cf la pause. Or, il semblerait que seul moto ait l'UC. Et plus bizarre encore, lorsque sigalarm est reçu, le programme se bloque…

    Pourriez-vous me dire ce qui provoque ces erreurs ?


    EDIT: J'ai compris une première erreur; wait peut être interrompu à la fois par un process fils se terminant mais aussi par un signal. Donc boucler deux fois n'est pas suffisant.

    Ici je peux prévoir le nombre de signal qui sera envoyé, donc ce n'est pas grave, mais dans le cas ou l'on ne peut pas prévoir ce nombre, comment pourrait on faire pour attendre la terminaison de tous les fils ?



    Ceci étant dit, ça ne m'explique pas pourquoi le programme se bloque...

  2. #2
    Membre chevronné
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2010
    Messages
    837
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2010
    Messages : 837
    Points : 2 247
    Points
    2 247
    Par défaut
    Faire une boucle autour d'un wait ?! Yurk ! Regarde plutôt sa valeur de retour pour voir ce qu'il s'est passé (en gros, tant qu'il retourne -1, ton process fils est vivant).
    Il y a 10 sortes de gens : ceux qui comptent en binaire et les autres.

    "Premature optimization is the root of all evil" --Donald Knuth
    traduction : "L'optimisation prématurée est la racine de tous les maux" -- Donald Knuth

    Si vous voulez apprendre à développer en Rust, un tuto (en français) est disponible ici.
    Si vous voulez voir mes projets, c'est sur github que ça se passe.

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    août 2011
    Messages
    745
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 745
    Points : 374
    Points
    374
    Par défaut
    Sauf que là j'en ai 2 de fils !

    Attendre la terminaison d'un fils ça je sais faire; mais attendre la terminaison de tous les fils ça me semble plus compliqué.

  4. #4
    Membre chevronné
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2010
    Messages
    837
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2010
    Messages : 837
    Points : 2 247
    Points
    2 247
    Par défaut
    Ce qui est une idée fort étrange en soi... Le mieux serait quand même de mettre un peu de récursivité là-dedans :

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdbool.h>
     
    void launch_process(bool launch_another) {
        pid_t pid = fork();
     
        if (pid < 0) {
            perror("Erreur fork");
            return;
        } else if (pid) {
            if (launch_another)
                moto();
            else
                voiture();
        } else {
            if (launch_another)
                launch_process(false);
            while (wait(0) == -1);
        }
    }
     
    int main() {
        launch_process(false);
        return 0;
    }
    Voilà qui est déjà nettement plus lisible.
    Il y a 10 sortes de gens : ceux qui comptent en binaire et les autres.

    "Premature optimization is the root of all evil" --Donald Knuth
    traduction : "L'optimisation prématurée est la racine de tous les maux" -- Donald Knuth

    Si vous voulez apprendre à développer en Rust, un tuto (en français) est disponible ici.
    Si vous voulez voir mes projets, c'est sur github que ça se passe.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 213
    Points : 40 894
    Points
    40 894
    Par défaut
    Mais il y a une erreur dans ton code actuel, non? Là si je le lis correctement, c'est le fils qui va lancer un petit-fils, et non le père qui va lancer les deux.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    août 2011
    Messages
    745
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : août 2011
    Messages : 745
    Points : 374
    Points
    374
    Par défaut
    Non, là on a bien deux fils.

    Pour avoir un petit fils il aurait fallu que le second fork soit dans le case 0 du premier fork.

    En revanche c'est vrai que c'est plus propre de l'écrire comme le présente imperio.

    A la base, je l'avais écris dans une boule, mais je l'ai déroulé pour faire des tests.

    Bien entendu il est mieux d'écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(k=0;k<2;k++)
       switch(pid[k]=fork()){
           case -1: //erreur
           case 0:
                   if(k==0) then moto() else voiture()
          default: break;
        }
    }
    Là clairement on voit mieux que les deux process sont bien crée par le même process.

    Si je met un wait, en attendant le pid, je peux attendre la fin d'un process, mais pas des deux. Ce qui serait bien ce serait d'avoir une fonction du style waitAll permettant d'attendre tous les process (peut toujours rêver^^)

  7. #7
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 1 303
    Points : 6 351
    Points
    6 351
    Par défaut
    Bonjour,

    Il est AMHA plus simple d'utiliser les threads et événements pour gérer les traitements parallèles.

    Avec les fork() et les signaux POSIX, il y a de nombreuses données à prendre en compte.
    * au moment du fork(), l'état intégral de l'application est cloné, ensuite chaque process vit sa vie (en particulier chacun des 3 gère ses propres variables START_...).
    * quand un signal est reçu
    a) ou le signal est totalement ignoré.
    b) ou le signal n'a pas d'action, mais un thread est débloqué.
    c) ou la callback du signal est appelée, pour cela un thread est débloqué.
    d) ou le process est tué (via un éventuel traitement de signal.)

    Ici, il y a 3 signaux :
    1. SIGUSR1, émis vers le 2nd fils 'voiture' qui change une variable (père et frère ne voient rien)
    2. SIGALARM, émis vers le père après 10s (qui modifie motoGo que lui seul voit changer!)
    3. SIGCHILD, émis par les deux fils vers leur père au moment de leur terminaison (cas (b)).

    La réception d'un signal débloque la plupart des fonctions d'attente (ici wait() ou pause())

    Et tout cela en parallèle (p.e, le SIGUSR1 est-il reçu par voiture avant ou après son démarrage?, ...)
    Complexe

Discussions similaires

  1. signaux et alarmes linux
    Par Nymar dans le forum Linux
    Réponses: 5
    Dernier message: 18/03/2013, 15h28
  2. [Amstrad] Signaux à gérer port E/S pour lire ROM
    Par Masterglob dans le forum Autres architectures
    Réponses: 7
    Dernier message: 12/01/2005, 12h03
  3. [INFO]Signaux Linux et Java
    Par el3gans dans le forum Général Java
    Réponses: 5
    Dernier message: 26/11/2004, 00h17
  4. [C#] Gérer les signaux genre ctrl+c?
    Par BleudeBromothymol dans le forum Windows Forms
    Réponses: 8
    Dernier message: 17/11/2004, 15h32
  5. [langage] alarm( MILLISECONDES ?????)
    Par armada dans le forum Langage
    Réponses: 8
    Dernier message: 10/06/2003, 09h00

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