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

C Discussion :

Modifier variable périodiquement


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2006
    Messages : 71
    Par défaut Modifier variable périodiquement
    Bonjour,

    J'aimerais incrémenter périodiquement une certaine variable au cours de l'exécution de mon programme.
    Typiquement, le programme appelle régulièrement une certaine fonction, grâce à la fonction alarm() et l'utilisation d'un handler. Or j'aimerai compter le nombre de fois où cette fonction handler est appelée.
    Or j'ai lu qu'il n'était pas bon de modifier des variables globales à partir du handler, et que celui-ci devait agir de manière confinée (pas d'interaction avec les variables du programme).

    Alors, comment faire ? Existe-t-il une solution ?

    Merci.

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2006
    Messages : 71
    Par défaut
    En fait mon problème est même d'ordre plus général :

    comment effectuer, à intervalles de temps réguliers, un certain traitement, qui implique la lecture de variables du programme, et à moindre mesure l'écriture (uniquement incrémenter un compteur), et ce de manière asynchrone.
    C'est à dire que le programme peut très bien être en train de calculer ou en attente de message, etc...

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Lorsque 2 threads ou plus tentent d'accèder à une même variable, il faut protéger la variable.

    Dans ton cas, tes 2 threads sont le programme principal et le handler de traitement des signaux

    Pour protéger ta variable, il y a plein de possibilités, la plus simple étant probablement la section critique.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par MarronSuisse Voir le message
    En fait mon problème est même d'ordre plus général :

    comment effectuer, à intervalles de temps réguliers, un certain traitement, qui implique la lecture de variables du programme, et à moindre mesure l'écriture (uniquement incrémenter un compteur), et ce de manière asynchrone.
    C'est à dire que le programme peut très bien être en train de calculer ou en attente de message, etc...
    http://emmanuel-delahaye.developpez.com/pthreads.htm

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2006
    Messages : 71
    Par défaut
    Arg, je pensais pouvoir éventuellement pouvoir me passer des threads puisque le traitement n'a pas nécessairement besoin d'être effectué en parallèle, mais apparemment y'a pas trop le choix

    Je sais ce qu'il me reste à faire..

  6. #6
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Si tu peux te passer des threads :
    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
    #include <stdio.h>
    #include <signal.h>
    #include <unistd.h>
     
    void handler (int);
     
    static volatile sig_atomic_t var = 0;
     
    int main (void)
    {
       signal (SIGALRM, handler);
     
       for (int i = 0; i < 10000; i++)
       {
          var++;
          if (i % 1000 == 0)
             raise (SIGALRM);
       }
     
       printf ("resulat attendu : 10010\n"
               "resultat obtenu : %d\n"
               "%s\n", var, 10010 == var ? "success" : "fail");
       return 0;
    }
     
    void handler (int sig)
    {
       var++;
       signal (SIGALRM, handler);
    }

  7. #7
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par nicolas.sitbon Voir le message
    Si tu peux te passer des threads :
    Etait-il précisé 'sous unixoïde' ?
    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
     
    Project   : Forums
    Compiler  : GNU GCC Compiler (called directly)
    Directory : D:\dev\forums\
    --------------------------------------------------------------------------------
    Switching to target: default
    Compiling: main.c
    main.c: In function `main':
    main.c:11: error: `SIGALRM' undeclared (first use in this function)
    main.c:11: error: (Each undeclared identifier is reported only once
    main.c:11: error: for each function it appears in.)
    main.c:13: error: 'for' loop initial declaration used outside C99 mode
    main.c: In function `handler':
    main.c:29: error: `SIGALRM' undeclared (first use in this function)
    main.c: At top level:
    main.c:26: warning: unused parameter 'sig'
    Process terminated with status 1 (0 minutes, 1 seconds)

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2006
    Messages : 71
    Par défaut
    J'ai découvert la fonction setitimer qui correspond exactement à ce dont j'avais besoin : elle permet l'envoi du signal SIGALRM à un intervalle de temps choisi, ce qui permet d'exécuter périodiquement une action en parallèle de l'exécution du programme.

    Sauf que j'aimerais exécuter plusieurs traitements périodiques (de période différente). Or setitimer ne permet que d'envoyer le signal SIGALRM, donc il n'y a pas moyen de distinguer quel traitement appliquer lors de la réception du signal. Existe-t-il une fonction qui permettrait d'envoyer périodiquement un autre type de signal, pour pouvoir associer un traitement différent à chaque signal périodique ?

  9. #9
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    timer_create() + signaux temps réels, feront ce que tu demandes.

  10. #10
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    bah sinon setitimer ou SIGALRM et tu gères dans un petit tableau les différents cas.. Pas si compliqué que ça..

  11. #11
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2006
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2006
    Messages : 71
    Par défaut
    Je me suis renseigné, la plateforme vers laquelle sera porté le code ne supporte pas les signaux temps réels...

    bah sinon setitimer ou SIGALRM et tu gères dans un petit tableau les différents cas.. Pas si compliqué que ça..
    Au risque de paraître totalement stupide... : je ne vois pas comment !
    Puisqu'on ne peut définir qu'une seule alarme avec setitimer. Lorsqu'on rappelle setitimer, la nouvelle alarme périodique remplacera la première.
    De plus, quand bien même on pourrait définir plusieurs alarmes de périodes différentes, comment savoir dans le handler de quelle alarme le signal provient ? Puisque l'alarme ne peut transporter aucune information avec elle !


  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    facile..

    Tu fais un petit tableau de structures dans lequel tu stockes tes infos :

    Intervalle
    Fonction à appeler
    Data à passer

    Du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct pMyTimer {
           int Intervalle ;
           int NextCall ; 
           int *Fct ;
           void *Data ;
    }  MyTimer ;
    (dans ce cas les fonctions à appeler sont du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Fonction(void *Data)
    )

    Puis tu déclares dans ton module :

    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
    MyTimer *MyTimers ;
    int          NTimers=0 ;
    
    ....
    
    RegisterTimer ( int intervalle, int FirstCall, (int *)&MaFonction, (void *)MyData )
    {
        /* Reallocation de la structure */
     
        MyTimers[NTimers].Intervalle = intervalle ;
         ......
    
        /* Et ici tu appelles une routine qui re-calcule le nouveau prochain
         *  declenchement, en passant à travers tous les timers, calculant le
         * plus proche , settant le setitimer avec ce chiffre. et calculant la 
         * date du prochain appel pour chacun (NextCall). 
         */ 
        RecomputeTimer ();
    }
    
    void RecomputeTimer ( void )
    {
      int i, MinTime=INT_MAX;
      time_t now ;
    
      now = time(NULL); /* Pour une precision a la seconde */
       /* Pour une précision à la micro, voir ma fonction dans les sources */
    
       for ( i = 0 ; i < NTimers ; i++ )
        {
           if ( Timers[i].NextCall <= now ) /* Voir remarque plus haut */
             {
                 /* Appelle la fonction pour ce timer */ 
                .........
    
               /* Calcule le prochain appel */
              Timers[i].NextCall  =  Timers[i].NextCall + Timers[i].Intervalle ;
    
               /* Verifie si ce sera le prochain a appeler */
               if ( Timers[i].NextCall < MinTime )
                  MinTime = Timers[i].NextCall ;
             }
            else
            {
                /* Pour ceux qui n'ont pas expire, verifie aussi si c'est le prochain */
               if ( Timers[i].NextCall < MinTime )
                  MinTime = Timers[i].NextCall ;
            }
        }
    
       /* Et la reset le timer general */
        setitimer ( ....);
    }
    pas compliqué

    et ton signal-handler ne fait qu'appeller cette routine RecomputeTimer();

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

Discussions similaires

  1. [Tableaux] modifier variable $_GET
    Par goldorax113 dans le forum Langage
    Réponses: 9
    Dernier message: 09/05/2007, 11h42
  2. Modifier variable dans une méthode
    Par dondano dans le forum Langage
    Réponses: 6
    Dernier message: 12/04/2007, 16h50
  3. Réponses: 3
    Dernier message: 13/04/2006, 21h55
  4. Modifier variable php suite à un clique
    Par budiste dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 29/11/2005, 16h06
  5. [D6] Modifier variable environnement système !?
    Par Lung dans le forum API, COM et SDKs
    Réponses: 32
    Dernier message: 19/05/2005, 19h43

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