Программирование PC Linux: задержки в программе на языке C Fri, October 11 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Linux: задержки в программе на языке C Печать
Добавил(а) microsin   

Задержки в программе на языке C можно реализовать функциями sleep, nanosleep, usleep.

sleep. Функция sleep предоставляет вероятно самый простой способ удерживать программу в состоянии ожидания на короткий интервал времени. Если ваша программа не использует сигналы (за исключением terminate), то можете быть уверены, что sleep обеспечит ожидание на указанный интервал времени. Иначе sleep может прервать ожидание и сделать возврат, если будет получен сигнал. Если вы хотите получить ожидание, независящее от сигналов, то используйте select (см. [3]) и не указывайте никакие дескрипторы для ожидания.

unsigned int sleep (unsigned int seconds);

Preliminary: | MT-Unsafe sig:SIGCHLD/linux | AS-Unsafe | AC-Unsafe | см. концепции безопасности POSIX [4].

Функция sleep ждет (блокирует выполнение кода) для указанного количества секунд seconds, или до момента доставки сигнала - что произойдет раньше.

Если выход из sleep произошел по причине истечения указанного интервала времени, то sleep возвратит 0. Если возврат произошел по причине получения сигнала, то возвращенное значение будет равно оставшемуся времени, которое не успело пройти.

Функция sleep декларирована в заголовке unistd.h.

Избегайте искушения реализовать задержку на фиксированное количество времени, используя значение, возвращаемое из sleep, когда оно не равно 0, чтобы вызвать sleep еще раз. Это будет работать с некоторой точностью, пока сигналы поступают нечасто. Но каждый сигнал может привести к тому, что возможное время пробуждения будет уменьшено на дополнительную секунду или около того. Предположим, что несколько сигналов приходят в быстрой последовательности, и в таком случае нет никаких ограничений на то, насколько может быть сокращено время ожидания.

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

В некоторых системах sleep может делать странные вещи, если ваша программа явно использует SIGALRM. Даже если сигналы SIGALRM игнорируются или блокируются, когда вызывается sleep, функция sleep все равно может выполнить возврат при доставке сигнала SIGALRM. Если вы установили обработчик для сигналов SIGALRM, и был доставлен сигнал SIGALRM во время работы sleep, то в результате может произойти выход из sleep вместо вызова вашего обработчика. И если sleep прерывается доставкой сигнала, обработчик которого запрашивает alarm или изменяет обработку SIGALRM, то этот обработчик и sleep будут мешать друг другу.

В системах GNU можно безопасно использовать sleep и SIGALRM в одной программе, потому что sleep не работает посредством SIGALRM.

nanosleep. Если разрешающей способности в секундах недостаточно, то может использоваться функция nanosleep. Имя этой функции подсказывает, что интервал задержки можно указывать в наносекундах. Реальное время ожидания может быть больше, поскольку система округляет прошедшее время до следующего целого числа, кратного физическому разрешению системы аппаратуры отсчета времени.

int nanosleep (const struct timespec *requested_time,
               struct timespec *remaining);

Preliminary: | MT-Safe | AS-Safe | AC-Safe | см. концепции безопасности POSIX [4].

В параметре *requested_time указывается интервал времени для задержки. Через *remaining возвращается оставшееся количество времени, которое еще не успело пройти. Если указанное время ожидания не было прервано поступлением сигнала, то это значение будет равно 0.

Структура timespec описана в [5].

Если возврат произошел по истечению указанного времени, то функция nanosleep вернет 0. Если функция nanosleep возвратила -1, то глобальная переменная errno установится в следующие значения:

EINTR: вызов был прерван из-за того, что в поток был доставлен сигнал. Если параметр remaining не был указан как NULL, то структура, на которую указывает remaining, будет заполнен оставшимся значением времени.
EINVAL: значение наносекунд в параметре requested_time содержит недопустимую величину. Либо используется отрицательное значение, либо оно больше или равно 1000 миллионов.

Эта функция является точкой отмены (cancellation point) в многопоточных программах. Это проблема, если поток выделяет некоторые ресурсы (например, память, файловые дескрипторы, семафоры или что-то еще) во время вызова nanosleep. Если поток отменяется, эти ресурсы остаются выделенными до окончания программы. Чтобы избежать этого, вызовы nanosleep должны быть защищены с помощью обработчиков отмены.

Функция nanosleep определена в заголовке time.h.

Пример использования:

#include < time.h>
 
void delay_ms (uint32_t ms)
{ struct timespec delta = (struct timespec){0, ms*1000*1000}; while (nanosleep(&delta, &delta));
}

usleep. Старые стандарты POSIX определяют функцию usleep, которая доступна в Linux:

int usleep(useconds_t usec);

Функция usleep приостановит выполнения потока, где она была вызвана на (как минимум) usec микросекунд. Время задержки выполнения может быть несколько увеличено любой активностью системы или на время, затраченное на обработку вызова, или детализацией системных таймеров.

[Ссылки]

1. sleep nanosleep site:gnu.org.
2. Is there an alternative sleep function in C to milliseconds? site:stackoverflow.com.
3. Waiting for Input or Output site:gnu.org.
4. POSIX Safety Concepts site:gnu.org.
5. Time Types site:gnu.org.
6Альтернатива функции Sleep для реализации задержки в миллисекундах.

 

Добавить комментарий


Защитный код
Обновить

Top of Page