Таймеры POSIX и обработка сигналов POSIX - PullRequest
1 голос
/ 25 января 2012

Я разрабатываю простое программное обеспечение, чтобы проверить, могу ли я программировать, используя то, что я изучил о таймерах и сигналах POSIX.

Я пытаюсь создать простую программу, которая запускает таймер и излучает сигнал.определенное количество наносекунд

Следующая программа не работает должным образом, поэтому я написал несколько комментариев о своем коде, чтобы вы могли проверить, правильно ли я учился или нет.Вы можете найти полный список кодов внизу страницы.

Различные отпечатки, например

prinf("1\n")
, предназначены для проверки преждевременного выхода из программы.Я поместил
struct sigevent sigeventStruct
как структуру для событий истечения, генерируемых таймером.Первый параметр установлен в SIGEV_SIGNAL, так что это тип сигнала, который он будет излучать./// Различные наборы mem, которые вы можете прочитать в листинге кода, относятся к нулю инициализированных структур.
if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)

- для создания таймера POSIX.POSIX MONOTONIC CLOCK - это тип таймера, а sigeventStruct - указатель на структуру, которая описывает, как это событие генерируется истечением таймера.& timer1 - указатель на имя определенного таймера.

if(timer_settime(timer1, NULL, &tempoIniziale, &tempoFinale) == -1)

с помощью этой процедуры таймер активируется, поэтому вы можете заставить его генерировать истечения.timer1 - имя таймера, 0 - флаги.Книга GAPIL гласит: <> & tempoIniziale и & tempoFinale являются указателями на структуры itimerspec.Я не очень хорошо понял, в чем смысл & old_timer.В книге GAPIL вы можете прочитать: <>

struct sigaction, oldSigAzione

структуры sigaction, которые будут переданы в качестве параметра обработчику сигналов sosaction POSIX

sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione)

SIGEV_SIGNAL - это тип сигналов, с которыми он должен обрабатывать, NULL - это место, где можно разместить указатель на структуру sigaction, а oldSigAzione - указатель на структуру sigaction, о которой я упоминал ранее.Здесь я опять не понял разницы между этими двумя указателями на структуру sigaction.

Мой вопрос: почему программа завершает работу перед печатью числа 19 из printf ("19 \ n");и почему не исключает printf ("Таймер scaduto \ n");внутренняя функция void termination_handler (int signum)?

Вот мой код:

#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 Ответ

5 голосов
/ 26 января 2012

При вызове timer_create() первым аргументом должен быть идентификатор часов, например CLOCK_MONOTONIC. _POSIX_MONOTONIC_CLOCK - это просто макрос, который можно использовать для проверки во время компиляции, поддерживает ли система CLOCK_MONOTONIC.

Первый аргумент sigaction() должен быть номером сигнала, а не SIGEV_SIGNAL. В вашем случае вы используете сигнал 10, но это не очень хороший выбор, потому что обычно это будет один из предопределенных сигналов ОС. Обычно вы используете определяемый пользователем сигнал, например SIGUSR1, или сигнал в реальном времени, например SIGRTMIN, поскольку они определены для использования приложением. Также ваш вызов sigaction() не устанавливает обработчик сигнала, потому что второй аргумент - NULL. Второй аргумент должен быть указателем на ваше новое действие сигнала. Вместо этого вы используете третий аргумент, который используется для возврата предыдущего действия сигнала. Это позволяет вам временно установить новое действие сигнала, сохранив старое действие сигнала, а затем, когда вы закончите с новым действием, вы можете вернуть его к сохраненному значению. Поскольку вы никогда не меняете его снова, вам не нужно получать старое значение. Также, чтобы быть устойчивым, действие сигнала должно быть установлено перед запуском таймера, так как выполнение вашей программы может быть отложено (например, если система действительно зависает), и таймер может истечь до того, как вы достигнете точки в вашем коде, где вы установили обработчик сигнала.

И, как упоминалось в R, printf() не безопасен для асинхронных сигналов, поэтому его не следует вызывать из обработчика сигналов.

...