C ile milisaniyeler arasında alternatif bir uyku işlevi var mı?


133

Windows'ta derlenmiş bazı kaynak kodum var. Red Hat Linux üzerinde çalışacak şekilde dönüştürüyorum.

Kaynak kodu <windows.h>başlık dosyasını içerir ve programcı Sleep()işlevi milisaniyelik bir süre beklemek için kullanır. Bu, Linux'ta çalışmaz.

Bununla birlikte, sleep(seconds)işlevi kullanabilirim , ancak bu, saniye cinsinden tamsayı kullanır. Milisaniyeleri saniyeye dönüştürmek istemiyorum. Linux'ta gcc derlemesiyle kullanabileceğim alternatif bir uyku işlevi var mı?


sleep(/*seconds*/)içinde <unistd.h>ı ile kullanırsanız eserler, ancak printf("some things")olmadan \n, onun değil çalışır.
EsmaeelE

Bu durumda kullanmak için, çıktıyı fflush(stdout);her printf()
birinden

Yanıtlar:


179

Evet - eski POSIX standartları tanımlanmıştır usleep(), bu nedenle bu Linux'ta mevcuttur:

   int usleep(useconds_t usec);

AÇIKLAMA

Usleep () işlevi, çağıran iş parçacığının yürütülmesini (en azından) usec mikrosaniye için askıya alır. Uyku, herhangi bir sistem aktivitesi veya aramanın işlenmesi için harcanan süre veya sistem zamanlayıcılarının ayrıntı düzeyi nedeniyle biraz uzatılabilir.

usleep()mikrosaniye alır , bu nedenle milisaniye içinde uyumak için girişi 1000 ile çarpmanız gerekir.


usleep()o zamandan beri kullanımdan kaldırıldı ve daha sonra POSIX'ten kaldırıldı; yeni kod nanosleep()için tercih edilir:

   #include <time.h>

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

AÇIKLAMA

nanosleep()en azından içinde belirtilen süre geçene kadar ya da çağıran iş parçacığındaki *reqbir işleyicinin çağrılmasını tetikleyen ya da süreci sonlandıran bir sinyalin teslimine kadar çağıran evrenin yürütülmesini askıya alır .

Zaman belirtimi yapısı, nanosaniye hassasiyetiyle zaman aralıklarını belirtmek için kullanılır. Aşağıdaki gibi tanımlanır:

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

Bir sinyalle kesintiye uğrarsa uykuya devam ederek msleep()uygulanan örnek bir işlev 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
Neden karmaşık işlevler için basit işlevleri kullanımdan kaldırıyorlar? Beyninizi nanosaniyede () bozmak yerine şimdilik uykumuzu kullanabiliriz.

52

Bu çapraz platform işlevini kullanabilirsiniz:

#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
Sahip olmadığımızda _POSIX_C_SOURCE >= 199309L, -ansiveya durumunda olduğu gibi, yerine -std=c89kullanmanızı tavsiye ederim . Kredi buraya gelir . struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);usleep(milliseconds * 1000);
Josh Sanford

Mükemmel cevap! Not, nanosleep()belgeler şu şekildedir : man7.org/linux/man-pages/man2/nanosleep.2.html . Burada kullanılan her platforma özgü işlev için dokümantasyon bağlantılarını yayınlamak faydalı olacaktır.
Gabriel Staples

Ayrıca birlikte derleme yaparken dikkat gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testgcc sürümü 4.8.4 ile Linux Ubuntu üzerine, şu uyarıyı alıyorum: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. Çözüm, kodunuzun en üstüne aşağıdaki 2 tanımı eklemektir: 1) #define __USE_POSIX199309ve 2) #define _POSIX_C_SOURCE 199309L. Her ikisinin de kodun herhangi bir uyarı olmadan derlenmesi (ve ayrıca nanoseconds()mevcut olan işlevi de kullanması ) gerekir.
Gabriel Staples

Az önce verdiğim ilgili cevap: stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

usleep()POSIX 2008'de tanımlanmayan seçeneğe alternatif olarak (POSIX 2004'e kadar tanımlanmış olsa da ve Linux ve POSIX uyumluluğu geçmişine sahip diğer platformlarda açıkça mevcuttur), POSIX 2008 standardı nanosleep()şunları tanımlar :

nanosleep - yüksek çözünürlüklü uyku

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

nanosleep()İşlevi tarafından belirli bir zaman aralığı ya kadar mevcut iplik yürütme askıya alınmasına neden olacaktır rqtpargüman geçtikten veya bir sinyal arayarak iplik teslim edilir, ve eylem bir sinyal alıcı fonksiyonu çağırmak için veya işlemi sonlanmasıdır. Bağımsız değişken değeri uyku çözünürlüğünün bir tam sayı katına yuvarlandığından veya diğer aktivitenin sistem tarafından programlanmasından dolayı askıya alma süresi talep edilenden daha uzun olabilir. Ancak, bir sinyalin kesintiye uğraması durumu haricinde, askıya alma süresi, rqtpCLOCK_REALTIME sistem saati ile ölçüldüğü üzere, ile belirtilen süreden daha az olmamalıdır .

nanosleep()Fonksiyonun kullanımının herhangi bir sinyalin eylemi veya engellenmesi üzerinde hiçbir etkisi yoktur.


24

Biz uykunun ötesinde , NULL dosya tanımlayıcı setleriyle mütevazı seçim , mikrosaniye hassasiyetinde ve SIGALRMkomplikasyon riski olmadan duraklamanıza izin verir .

sigtimedwait ve sigwaitinfo benzer davranışlar sunar.


1
'sigalarm riski olmadan': hangi risk ve hangi durum? uyku ve uykuyu çağırmak?
Massimo

2
@Massimo için bağlantılı Spec usleep belirtilmemiş SIGALARM davranışı üzerinde bazı cümleler vardır. (Temel olarak, usleep ve uyku eski aracılığıyla uygulanması için izin verilen alarm sen güvenli kullanımını karmaşık hale getirecek tahmin edebilirsiniz mekanizması, usleep ben bu şekilde yapar herhangi bir modern sistemin bilmiyorum. Ve SIGALARM ama hâlâ 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
Bu, milisaniyeler boyunca uyumaz ve ayrıca çok daha fazla yük getirir, bu da zamanlamayı daha da güvenilmez hale getirir.
Devolus

1
Örnek, mikrosaniyeler için uyumaz, ayrıca bu, usleep () gibi bir şey kullanmaya kıyasla o kadar da iyi bir çözüm değildir.
Victor Ocampo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.