Есть ли в C функция сна, альтернативная миллисекундам?


133

У меня есть исходный код, который был скомпилирован в Windows. Я конвертирую его для работы в Red Hat Linux.

Исходный код включает <windows.h>файл заголовка, и программист использовал Sleep()функцию для ожидания в течение миллисекунд. В Linux это не сработает.

Однако я могу использовать sleep(seconds)функцию, но она использует целое число в секундах. Я не хочу переводить миллисекунды в секунды. Есть ли альтернативная функция сна, которую я могу использовать при компиляции gcc в Linux?


sleep(/*seconds*/)в <unistd.h>работает, но если я использую printf("some things")без \n, он не работает.
EsmaeelE

Для использования в этом случае мы должны fflush(stdout);printf()
сбрасывать

Ответы:


179

Да - определены более старые стандарты POSIXusleep() , поэтому это доступно в Linux:

   int usleep(useconds_t usec);

ОПИСАНИЕ

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

usleep()занимает микросекунды , поэтому вам придется умножить ввод на 1000, чтобы засыпать в миллисекундах.


usleep()с тех пор устарел и впоследствии был удален из POSIX; для нового кода nanosleep()предпочтительно:

   #include <time.h>

   int nanosleep(const struct timespec *req, struct timespec *rem);

ОПИСАНИЕ

nanosleep()приостанавливает выполнение вызывающего потока до тех пор, пока не истечет, по крайней мере, время, указанное в *req, или пока не будет доставлен сигнал, запускающий вызов обработчика в вызывающем потоке или завершающий процесс.

Структура timespec используется для указания интервалов времени с точностью до наносекунды. Это определяется следующим образом:

       struct timespec {
           time_t tv_sec;        /* seconds */
           long   tv_nsec;       /* nanoseconds */
       };

Пример msleep()функции, реализованной с использованием nanosleep()продолжения сна, если он прерван сигналом:

#include <time.h>
#include <errno.h>    

/* msleep(): Sleep for the requested number of milliseconds. */
int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

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

52

Вы можете использовать эту кроссплатформенную функцию:

#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>   // for nanosleep
#else
#include <unistd.h> // for usleep
#endif

void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
    Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
#else
    usleep(milliseconds * 1000);
#endif
}

3
Когда у нас нет _POSIX_C_SOURCE >= 199309L, как в случае -ansiили -std=c89, я бы рекомендовал использовать struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);вместо usleep(milliseconds * 1000);. Кредит идет сюда .
Джош Сэнфорд

Отличный ответ! Обратите внимание, вот nanosleep()документация: man7.org/linux/man-pages/man2/nanosleep.2.html . Было бы полезно разместить ссылки на документацию для каждой используемой здесь функции для конкретной платформы.
Габриэль Стейплс

Также обратите внимание , что при компиляции с gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testна Linux Ubuntu с GCC версии 4.8.4, я получаю следующее предупреждение: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. Решение состоит в том, чтобы добавить следующие 2 определения в самый верх вашего кода: 1) #define __USE_POSIX199309и 2) #define _POSIX_C_SOURCE 199309L. Оба необходимы для компиляции кода без каких-либо предупреждений (а также для использования nanoseconds()функции, которая у него есть).
Габриэль Стейплс

Связанный ответ, который я только что сделал: stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

В качестве альтернативы тому usleep(), что не определено в POSIX 2008 (хотя оно было определено до POSIX 2004 и очевидно доступно на Linux и других платформах с историей соответствия POSIX), стандарт POSIX 2008 определяет nanosleep():

nanosleep - сон высокого разрешения

#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

nanosleep()Функция должна вызвать текущий поток быть отстранен от выполнения до либо временной интервал , указанный в rqtpаргументе не истечет или сигнал доставляется вызывающей нити, и его действие для вызова функции сигнала выделяющийся или прекратить процесс. Время приостановки может быть больше запрошенного, поскольку значение аргумента округлено до целого кратного разрешения сна или из-за планирования других действий системой. Но, за исключением случая прерывания сигналом, время приостановки не должно быть меньше времени, указанного в rqtp, как измерено системными часами CLOCK_REALTIME.

Использование nanosleep()функции не влияет на действие или блокировку любого сигнала.


24

Помимо usleep , скромный выбор с набором файловых дескрипторов NULL позволит вам делать паузу с точностью до микросекунд и без риска SIGALRMосложнений.

sigtimedwait и sigwaitinfo предлагают аналогичное поведение.


1
«без риска сигалармы»: какой риск и в каком случае? зовет спать и уснуть?
Massimo

2
@Massimo, связанная спецификация для usleep содержит несколько предложений о неуказанном поведении SIGALARM. (По сути, usleep и sleep могут быть реализованы через старый механизм сигнализации , который, как вы можете себе представить, усложнит безопасное использование usleep и SIGALARM. Я не знаю ни одной современной системы, которая делает это таким образом, но она все еще находится в spec.)
pilcrow


-7
#include <stdio.h>
#include <stdlib.h>
int main () {

puts("Program Will Sleep For 2 Seconds");

system("sleep 2");      // works for linux systems


return 0;
}

1
Это не спит в течение миллисекунд, а также приводит к гораздо большим накладным расходам, что делает синхронизацию еще более ненадежной.
Devolus

1
Пример не спит микросекунды, плюс это не очень хорошее решение по сравнению с простым использованием чего-то вроде usleep ().
Виктор Окампо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.