Механизмы таймера позволяют планировать, чтобы ядро ОС уведомляло приложение по истечении заданного времени. Обычно вы будете использовать их, предоставляя две части информации. Во-первых, вам нужно указать, сколько времени должно пройти таймер перед уведомлением. Во-вторых, вам нужно подготовить функцию обратного вызова, которая будет действовать при появлении этого уведомления.
Традиционный подход к таймерам
Механизмы таймера в системах на основе Linux и Unix эволюционировали, чтобы служить различным потребностям. Различные подходы могут помочь вам решить различные типы проблем. Тем не менее, вы часто будете видеть первую версию тревога() механизм работает до сих пор.
Функция будильника — самый простой способ использования таймера; вот его прототип:
неподписанныйинттревога(неподписанныйинт секунд);
Используя этот метод, вы можете указать время только в целых секундах. Когда время истекло, операционная система отправляет СИГАЛРМ сигнал для вашего приложения. Чтобы обработать истечение таймера в вашем приложении, вы также должны определить функцию обратного вызова.
Вот пример функции обработчика сигнала:
#включают
#включают
#включают
#включаютпустотаtimer_callback(инт знак)
{
время_t сейчас = время(НУЛЕВОЙ);
printf("Сигнал %d пойман на %li", сигнум, сейчас);
}
интглавный()
{
сигнал (SIGALRM, timer_callback);
тревога(1);
спать(3);
возвращаться0;
}
Этот код вызывает СИГАЛРМ сигнал после 1 второй. Если вы хотите увеличить задержку таймера до пяти секунд, просто позвоните будильник (5) вместо. Чтобы остановить таймер, передайте значение 0: будильник (0).
Когда время истекло, используемый вами таймер не будет периодически перезапускаться. Например, если вы хотите задержаться еще на секунду, вы должны перезапустить механизм другим вызовом тревога().
Несмотря на простоту использования, этот метод имеет некоторые недостатки:
- Только один таймер за раз.
- Нет поддержки периодического таймера.
- Вы можете указать только период времени, кратный целым секундам.
- Невозможно узнать, сколько времени осталось на таймере.
Сохраните приведенный выше пример кода как будильник.c. Когда вы компилируете и запускаете это, программа вызовет timer_callback функционировать через одну секунду. Затем он будет ждать оставшиеся две секунды из-за спать (3) линии, затем завершить.
$ gcc -o тревога alarm.c
$ время ./будильник
Сигнал 14 пойман на 1653490465
реальное 0м1.004с
пользователь 0м0.000с
система 0m0.003s
Причина использования команды времени состоит в том, чтобы иметь возможность видеть время. Но если посмотреть на результат, то общее время работы не три секунды. Это связано с СИГАЛРМ сигнал от будильник (1) когда первая секунда истекла, а системный вызов вызвано работой функции сна (3). Когда этот сигнал поступает, он прерывает системный вызов, инициированный для спать (3).
Использование интервального таймера
Механизм интервального таймера был впервые доступен в версии 4.2 BSD. Это было позже стандартизирован POSIX. Его основные преимущества перед традиционным тревога() на основе метода таймера:
- Обеспечивает микросекундное разрешение.
- Это позволяет более детально контролировать измерение времени в трех различных режимах.
- Можно установить один раз и заставить работать периодически.
- Можно узнать, как долго он присутствует в любой данный момент.
Прототипы функций, используемые для операций интервального таймера, следующие:
#включают
интустановка таймера(инт который, константа struct itimerval *newValue, struct itimerval *oldValue);
интгетимер(инт который, struct itimerval *value);структураитимервал
{
структуравременнойэтоИнтервал;// следующее значение
структуравременнойэтозначение;// текущая стоимость
};
структуравременной
{
длинная тв_сек;
длинная тв_усек;
};
Если вы хотите настроить интервальный таймер, вам нужно будет использовать итимервал структура. Вам нужно будет передать значение, используя эту структуру в качестве второго аргумента для таймер функция.
Например, интервальный таймер, который будет уведомлять ваше приложение в течение 1 секунды, а затем каждые 300 миллисекунд, можно настроить следующим образом:
структураитимервалновыйТаймер;
структураитимервалСтарожил;newTimer.itValue.tv_sec = 1;
новыйТаймер.itValue.tv_usec = 0;новыйТаймер.itInterval.tv_sec = 0;
новыйТаймер.itInterval.tv_usec = 300 * 1000;
setitimer (ITIMER_REAL, &newTimer, &oldTimer);
Если перед установкой новых значений активен интервальный таймер, его значения передаются по адресу переменной итимервал тип, присвоенный третьему параметру функции.
С помощью механизма интервального таймера можно настроить три разных типа таймеров. Укажите тип таймера в первом параметре установить таймер ():
Тип таймера | Сигнал | Объяснение |
---|---|---|
ITIMER_REAL | СИГАЛРМ | Независимо от времени, затраченного приложением, рассчитывается по общему прошедшему времени. |
ITIMER_VIRTUAL | СИГВТАЛРМ | Рассчитывается за время работы приложения только в пользовательском режиме. |
ITIMER_PROF | СИГПРОФ | Рассчитывается по сумме времени, проведенного приложением как в пользовательском, так и в системном режимах. |
Из этой таблицы видно, что ITIMER_REAL тип отправляет СИГАЛРМ сигнал, как и тревога() функция.
Использование интервального таймера и тревога() в одном и том же приложении будет путаница. Хотя вы можете сделать повторную проверку оставшегося времени с помощью получить таймер (), нет смысла использовать их одновременно.
Вот пример определения функции обработчика сигнала с помощью заголовок отладки:
#включают
#включают
#включают
#включают
#включают
#включают
#включают
#включают "./отладка.ч"пустотаtimer_callback(инт знак)
{
структуравременнойв настоящее время;
gettimeofday(&сейчас, НУЛЕВОЙ);
printf("Сигнал %d пойман на %li.%03лi", signum, now.tv_sec, now.tv_usec/ 1000);
}интглавный()
{
неподписанныйинт оставшийся = 3;структураитимервалновый_таймер;
структураитимервалСтарожил;новый_таймер.it_value.tv_sec = 1;
новый_таймер.it_value.tv_usec = 0;
новый_таймер.it_interval.tv_sec = 0;
новый_таймер.it_interval.tv_usec = 300 * 1000;setitimer (ITIMER_REAL, &new_timer, &old_timer);
сигнал (SIGALRM, timer_callback);пока (спать (осталось) != 0)
{
если (ошибка == EINTR)
debugf("Сон прерван сигналом");
еще
errorf("Ошибка сна %s", strerror (errno));
}
возвращаться0;
}
В приведенном выше коде используется спать() функцию ожидания в течение трех секунд. В это время запускается интервальный таймер сначала на одну секунду, затем с интервалом в 300 миллисекунд.
Для лучшего понимания сохраните и скомпилируйте пример кода с именем интервал.c:
$ gcc -o интервал interval.c
$ время ./интервал
Сигнал 14 пойман на 1653493614.325
отладка: сон прерван сигналом (основной interval.c: 36)
Сигнал 14 пойман на 1653493614.625
отладка: сон прерван сигналом (основной interval.c: 36)
Сигнал 14 пойман на 1653493614.925
отладка: сон прерван сигналом (основной interval.c: 36)
Сигнал 14 пойман на 1653493615.225
отладка: сон прерван сигналом (основной interval.c: 36)
Сигнал 14 пойман на 1653493615.525
...
Как видно из вывода после запуска таймера, он вызывает функцию обратного вызова каждые 300 миллисекунд.
Однако, подождав еще немного, вы заметите, что приложение не завершает работу. Он продолжает выполнять функцию обратного вызова каждые 300 миллисекунд. Если вы увеличите значение интервала в миллисекундах, вы увидите, что приложение завершает работу. Это связано с областью использования спать() функция.
Важность использования таймеров в Linux
Механизм таймера имеет большое значение, особенно для приложений реального времени. Это также решение, используемое для оптимизации производительности. Вы даже можете использовать его для измерения времени безотказной работы или задержки в вашем приложении. Важно использовать механизмы таймера для отслеживания прошедшего времени и событий временного перехода.
Как скомпилировать и установить программное обеспечение из исходного кода в Linux
Читать дальше
Похожие темы
- Программирование
- Программирование
- Советы по Linux
Об авторе
Инженер и разработчик программного обеспечения, фанат математики и технологий. Ему всегда нравились компьютеры, математика и физика. Он разработал проекты игровых движков, а также машинное обучение, искусственные нейронные сети и библиотеки линейной алгебры. Кроме того, продолжает работать над машинным обучением и линейными матрицами.
Подписывайтесь на нашу новостную рассылку
Подпишитесь на нашу рассылку технических советов, обзоров, бесплатных электронных книг и эксклюзивных предложений!
Нажмите здесь, чтобы подписаться