2012-01-25 3 views
1

Je suis en train de développer un logiciel simple pour vérifier si je peux programmer en utilisant ce que j'ai étudié sur les timers et les signaux POSIX.Gestion des temporisateurs POSIX et des signaux POSIX

Je suis en train de faire un programme simple qui démarre une minuterie et émet un signal d'une certaine quantité de nanosecondes

Le programme suivant ne I fonctionne pas bien, donc écrit des commentaires sur mon code afin que vous puissiez vérifier si J'ai correctement étudié ou non. Vous pouvez trouver la liste complète des codes au bas de la page.

Divers tirages comme

prinf("1\n")
doivent vérifier où le programme se termine prématurément. J'ai mis
struct sigevent sigeventStruct
comme structure pour les événements d'expirations générés par le temporisateur. Le premier paramètre est défini sur SIGEV_SIGNAL, c'est donc le type de signal qu'il émettra. /// Les différents memset que vous pouvez lire dans la liste de code sont à zéro structures initialisées.

if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)

est de créer un temporisateur POSIX. POSIX MONOTONIC CLOCK est le type de temporisateur, & sigeventStruct est le pointeur vers la structure qui décrit comment c'est l'événement généré par l'expiration du temporisateur. Timer1 est le pointeur sur le nom du temporisateur spécifique. & Avec cette procédure, le temporisateur est armé, de sorte que vous pouvez le faire générer des expirations. Timer1 est le nom de la minuterie, 0 est les drapeaux. Le livre GAPIL dit: <> & tempoIniziale et & tempoFinale sont des pointeurs vers les structures itimerspec. Je n'ai pas bien compris quelle est la signification de & old_timer. Dans le livre GAPIL vous pouvez lire: <>

struct sigaction, oldSigAzione

structs sigaction qui sera passé en paramètre à sigaction gestionnaire de signaux Posix

sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione)

SIGEV_SIGNAL est le genre de signaux qu'il doit gérer, NULL est où il pourrait être placé un pointeur vers une sigaction de structure const, & oldSigAzione est le pointeur vers la structure de sigaction que j'ai mentionnée auparavant. Là encore je n'ai pas compris la différence entre ces deux pointeurs vers la structure de sigaction.

Ma question est: pourquoi le programme se termine avant d'imprimer le numéro 19 de printf ("19 \ n"); et pourquoi n'exécute pas le printf ("Timer scaduto \ n"); à l'intérieur de la fonction void termination_handler (int signum)?

Voici mon code:

#include <string.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <time.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/fcntl.h> 
#include <sys/wait.h> 
#include <stdbool.h> 

void termination_handler(int signum) 
{ 
    printf("Timer scaduto\n"); 
} 

int main() 
{ 
    printf("Start\n"); 
    printf("1\n"); 
    struct sigevent sigeventStruct; // sigevent struct that will be used by timer1 timer 
    printf("2\n"); 
    memset(&sigeventStruct, 0, sizeof sigeventStruct); // zero initialize struct 
    printf("3\n"); 
    sigeventStruct.sigev_notify = SIGEV_SIGNAL; // kind of notification of timer1 expiration 
    printf("4\n"); 
    sigeventStruct.sigev_signo = 10; 
    printf("5\n"); 

    timer_t timer1; // create a timer identifier 
    printf("6\n"); 
    if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1) 
    { 
     printf("Errore timer_create: %s\n", strerror(errno)); 
    } 

    printf("7\n"); 
    struct itimerspec tempoIniziale; 
    printf("8\n"); 
    memset(&tempoIniziale, NULL, sizeof tempoIniziale); // zero initialize struct 
    printf("9\n"); 
    tempoIniziale.it_value.tv_nsec = 100000000; 
    //tempoIniziale.it_interval.tv_nsec = 10000; 
    printf("10\n"); 


    if(timer_settime(timer1, 0, &tempoIniziale, NULL) == -1) // timer armed 
    { 
     printf("Errore timer_settime: %s\n", strerror(errno)); 
    } 
    printf("11\n"); 
    for(int i = 0; i< 10; i++) 
    { 
     printf("ciclo %d\n", i); 
    } 

    struct sigaction oldSigAzione; 
    printf("12\n"); 
    memset(&oldSigAzione, 0, sizeof oldSigAzione); 
    printf("13\n"); 
    oldSigAzione.sa_handler = termination_handler; 
    printf("14\n"); 
    sigemptyset (&oldSigAzione.sa_mask); 

    printf("15\n"); 
    oldSigAzione.sa_flags = 0; 

    printf("16\n"); 
    sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione); 
    printf("17\n"); 
    if(oldSigAzione.sa_handler == SIG_IGN) 
    { 
     printf("Segnale ignorato\n"); 
    } 
    printf("18\n"); 
    for(int i = 0; i < 1000000000000; i++) 
    { 

    } 
    printf("19\n"); 
    printf("number of expirations %d\n", timer_getoverrun(timer1)); 
    return 0; 
} 
+1

Une boucle vide n'est pas le moyen de retarder. Un compilateur moderne le compilera sans code du tout. Essayez 'sleep' ... –

+1

De plus,' printf' n'est pas sûr pour les signaux asynchrones. Vous ne pouvez pas l'utiliser depuis un gestionnaire de signal à moins d'éviter tous les appels à des fonctions asynchrones dans le code qui pourraient être interrompues par le signal. –

Répondre

5

Dans l'appel à timer_create(), le premier argument doit être un clockid tel que CLOCK_MONOTONIC. _POSIX_MONOTONIC_CLOCK est juste une macro que vous pouvez utiliser pour tester au moment de la compilation si le système prend en charge CLOCK_MONOTONIC.

Le premier argument à sigaction() doit être le numéro de signal, pas SIGEV_SIGNAL. Dans votre cas, vous utilisez le signal 10, mais ce n'est pas un bon choix, car ce sera généralement l'un des signaux d'OS prédéfinis.Habituellement, vous utiliserez un signal défini par l'utilisateur comme SIGUSR1 ou un signal en temps réel comme SIGRTMIN, puisque ceux-ci sont définis pour une utilisation par l'application. De plus, votre appel à sigaction() ne définit pas de gestionnaire de signal car le second argument est NULL. Le deuxième argument devrait être un pointeur vers votre nouvelle action de signal. Au lieu de cela, vous utilisez le troisième argument qui est utilisé pour retourner l'action de signal précédente. Cela vous permet de définir une nouvelle action de signal temporairement, tout en sauvegardant l'ancienne action de signal, et lorsque vous avez terminé avec la nouvelle action, vous pouvez la remettre à la valeur enregistrée. Puisque vous ne le changez plus jamais, vous n'avez pas besoin d'obtenir l'ancienne valeur. Aussi, pour être robuste, l'action du signal doit être réglée avant de démarrer la minuterie, car l'exécution de votre programme pourrait être retardée (par exemple si le système est réellement embourbé) et le minuteur pourrait expirer avant d'atteindre le point le gestionnaire de signal. Et comme R mentionné, printf() n'est pas un signal asynchrone sûr, il ne devrait pas être appelé à partir de votre gestionnaire de signal.

+0

Merci beaucoup, votre aide a été précieuse –