Có chức năng ngủ thay thế trong C đến mili giây không?


133

Tôi có một số mã nguồn được biên dịch trên Windows. Tôi đang chuyển đổi nó để chạy trên Red Hat Linux.

Mã nguồn đã bao gồm <windows.h>tệp tiêu đề và lập trình viên đã sử dụng Sleep()hàm để chờ một khoảng thời gian tính bằng mili giây. Điều này sẽ không hoạt động trên Linux.

Tuy nhiên, tôi có thể sử dụng sleep(seconds)hàm, nhưng sử dụng số nguyên trong vài giây. Tôi không muốn chuyển đổi mili giây thành giây. Có một chức năng ngủ thay thế mà tôi có thể sử dụng với biên dịch gcc trên Linux không?


sleep(/*seconds*/)trong <unistd.h>các tác phẩm, nhưng nếu tôi sử dụng printf("some things")mà không có \n, nó không hoạt động.
EsmaeelE

Để sử dụng trong trường hợp này, chúng tôi phải fflush(stdout);printf()
xóa sạch

Câu trả lời:


179

Có - các tiêu chuẩn POSIX cũ hơn được xác định usleep(), do đó, điều này có sẵn trên Linux:

   int usleep(useconds_t usec);

SỰ MIÊU TẢ

Hàm us ngủ () tạm dừng thực thi chuỗi gọi trong (ít nhất) usec micro giây. Giấc ngủ có thể được kéo dài một chút bởi bất kỳ hoạt động hệ thống nào hoặc do thời gian xử lý cuộc gọi hoặc bởi độ chi tiết của bộ định thời hệ thống.

usleep()mất vài giây , do đó bạn sẽ phải nhân số đầu vào lên 1000 để ngủ trong một phần nghìn giây.


usleep()kể từ đó đã bị phản đối và sau đó bị xóa khỏi POSIX; đối với mã mới, nanosleep()được ưu tiên:

   #include <time.h>

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

SỰ MIÊU TẢ

nanosleep()đình chỉ việc thực hiện chuỗi cuộc gọi cho đến khi ít nhất là thời gian được chỉ định trong *reqđã trôi qua, hoặc việc phát tín hiệu kích hoạt việc gọi trình xử lý trong luồng gọi hoặc kết thúc quá trình.

Thời gian cấu trúc được sử dụng để xác định các khoảng thời gian với độ chính xác nano giây. Nó được định nghĩa như sau:

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

Một msleep()chức năng ví dụ được triển khai bằng cách sử dụng nanosleep(), tiếp tục chế độ ngủ nếu bị gián đoạn bởi tín hiệu:

#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;
}

18
Tại sao họ cứ phản đối các chức năng đơn giản cho các chức năng phức tạp. Thay vì làm hỏng bộ não của bạn trên nano giây () cũng có thể sử dụng chúng ta ngủ trong thời gian này.

52

Bạn có thể sử dụng chức năng đa nền tảng này:

#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
Khi chúng tôi không có _POSIX_C_SOURCE >= 199309L, như trong trường hợp -ansihoặc -std=c89, tôi sẽ khuyên bạn nên sử dụng struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);thay vì usleep(milliseconds * 1000);. Tín dụng ở đây .
Josh Sanford

Câu trả lời chính xác! Lưu ý, đây là nanosleep()tài liệu: man7.org/linux/man-pages/man2/nanos ngủ.2.html . Đăng các liên kết tài liệu cho từng chức năng dành riêng cho nền tảng được sử dụng ở đây sẽ hữu ích.
Gabriel Staples

Cũng lưu ý rằng khi biên dịch với gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testLinux Ubuntu, với phiên bản gcc 4.8.4, tôi nhận được cảnh báo sau : warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. Giải pháp là thêm 2 định nghĩa sau vào đầu mã của bạn: 1) #define __USE_POSIX199309và 2) #define _POSIX_C_SOURCE 199309L. Cả hai đều được yêu cầu để có được mã để biên dịch mà không có bất kỳ cảnh báo nào (và cũng sử dụng nanoseconds()chức năng mà nó có sẵn).
Gabriel Staples

Câu trả lời liên quan Tôi vừa thực hiện: stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

Ngoài ra usleep(), không được xác định trong POSIX 2008 (mặc dù được xác định theo POSIX 2004 và nó có sẵn trên Linux và các nền tảng khác có lịch sử tuân thủ POSIX), tiêu chuẩn POSIX 2008 xác định nanosleep():

nanosleep - giấc ngủ độ phân giải cao

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

Các nanosleep()chức năng có trách nhiệm gây ra các chủ đề hiện tại để được đình chỉ thi hành cho đến khi một trong hai khoảng thời gian xác định bởi các rqtplập luận đã trôi qua hoặc một tín hiệu được gửi đến các chủ đề kêu gọi, và hành động của nó là để gọi một chức năng tín hiệu bắt hoặc chấm dứt quá trình này. Thời gian tạm dừng có thể dài hơn yêu cầu vì giá trị đối số được làm tròn thành bội số nguyên của độ phân giải ngủ hoặc do hệ thống lập lịch cho hoạt động khác của hệ thống. Nhưng, ngoại trừ trường hợp bị gián đoạn bởi tín hiệu, thời gian treo không được nhỏ hơn thời gian được chỉ định bởi rqtp, như được đo bằng đồng hồ hệ thống CLOCK_REALTIME.

Việc sử dụng nanosleep()chức năng không có tác dụng đối với hành động hoặc tắc nghẽn của bất kỳ tín hiệu nào.


24

Ngoài giấc ngủ , lựa chọn khiêm tốn với bộ mô tả tệp NULL sẽ cho phép bạn tạm dừng với độ chính xác đến micro giây và không có nguy cơ SIGALRMbiến chứng.

sigtimedwait và sigwaitinfo cung cấp hành vi tương tự.


1
'không có rủi ro của sigalarm': rủi ro nào và trường hợp nào? Gọi ngủ và ngủ?
Massimo

2
@Massimo, spec liên kết cho usleep có một vài câu về hành vi SIGALARM không xác định. (Về cơ bản, usleepngủ được phép thực hiện thông qua cái cũ báo động cơ, mà bạn có thể tưởng tượng sẽ làm phức tạp sử dụng an toàn của usleep và SIGALARM. Tôi không biết về bất kỳ hệ thống hiện đại mà hiện nó theo cách này, nhưng nó vẫn còn trong spec.)
hương


-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
Điều này sẽ không ngủ trong một phần nghìn giây và cũng giới thiệu nhiều chi phí hơn, điều này làm cho thời gian thậm chí không đáng tin cậy hơn.
Devolus

Ví dụ không ngủ trong vài giây, cộng với đó không phải là giải pháp tốt so với việc chỉ sử dụng một cái gì đó như ngủ ().
Victor Ocampo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.