Чи є альтернативна функція сну в С до мілісекунд?


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()
EsmaeelE

Відповіді:


179

Так - визначені старі стандарти POSIXusleep() , тому це доступно в Linux:

   int usleep(useconds_t usec);

ОПИС

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

usleep()займає мікросекунди , тож вам доведеться помножити вхід на 1000, щоб спати в мілісекундах.


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

   #include <time.h>

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

ОПИС

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

Часовий спектр структури використовується для визначення інтервалів часу з наносекундною точністю. Він визначається наступним чином:

       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
Чому вони продовжують депресувати прості функції для складних функцій. Замість того, щоб розбивати мозок на наносекунді (), на даний момент також можна скористатися сплячим режимом.

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_testLinux 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
Габріель Стейплз

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

Крім сну , скромний вибір з наборами дескрипторів файлів NULL дозволить зробити паузу з точністю до мікросекунди та без ризикуSIGALRM ускладнень.

sigtimedwait і sigwaitinfo пропонують подібну поведінку.


1
"без ризику виникнення сигаларми": який ризик і в якому випадку? закликає спати і спити?
Массімо

2
@Massimo, пов'язана специфіка для usleep має кілька пропозицій щодо не визначеної поведінки SIGALARM. (В основному режим сну і сну дозволяється здійснювати за допомогою старого механізму тривоги , який, як ви можете уявити, ускладнить безпечне використання режиму сну і SIGALARM. Я не знаю жодної сучасної системи, яка б це робила так, але вона все ще знаходиться в спец.)
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
Це звичайний сон протягом мілісекунд, а також вносить набагато більше накладних витрат, що робить час ще більш ненадійним.
Деволус

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