我如何暂停然后恢复对“睡眠”的呼叫

Mat*_*roh 5 c linux bash time sleep

呼唤 sleep(10)意味着睡眠指定的秒数。当我键入“ sleep 10”时,我想等待10秒,但是当我SIGTSTP在sleep命令之后立即使用CTRL-Z(或发送)时,即使该过程也不会停止“ timer”(或计数器)已经停止。

我可以看到jobs状态sleep更改为,STOPPED但是如果我等待10秒钟,然后将此过程发送到前台,它将,即使它运行的时间少于10秒钟,立即完成

因此,我的问题是如何停止睡眠计时器的运行?

更新 ::我现在了解睡眠使用的是时钟时间,因此如何使用用户cpu时间实现睡眠

o11*_*11c 2

sleep(3)返回被信号中断时剩余的秒数,但秒的粒度很差,因此最好使用clock_nanosleep(2).

\n\n

clock_nanosleep还有一个优点是允许您指定您想用哪种时钟睡觉 - 至少有 7 种不同的时钟,每种时钟在不同的情况下都有用。但很可能你想要CLOCK_MONOTONIC。(请注意,您在睡眠时使用CPU 时间,因此您绝对不希望这样做CLOCK_PROCESS_CPUTIME_ID(这在多线程进程中是有意义的))

\n\n

引用后一个手册页:

\n\n
   If the call is interrupted by a signal handler, clock_nanosleep() fails\n   with the error EINTR.  In addition, if remain is not  NULL,  and  flags\n   was not TIMER_ABSTIME, it returns the remaining unslept time in remain.\n   This value can then be used to call clock_nanosleep()  again  and  com\xe2\x80\x90\n   plete a (relative) sleep.\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:我最终编写了一个程序来演示您需要做什么,以及各种时钟之间的差异:

\n\n
/*\n    Requires adding\n        -pthread -lrt\n    to your command line.\n */\n#define _POSIX_C_SOURCE 200112L\n\n#include <assert.h>\n#include <ctype.h>\n#include <errno.h>\n#include <limits.h>\n#include <pthread.h>\n#include <signal.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\nstruct all_times\n{\n    struct timespec realtime;\n\n#ifdef CLOCK_REALTIME_COARSE\n    struct timespec realtime_coarse;\n#endif\n\n    struct timespec monotonic;\n\n#ifdef CLOCK_MONOTONIC_COARSE\n    struct timespec monotonic_coarse;\n#endif\n\n#ifdef CLOCK_MONOTONIC_RAW\n    struct timespec monotonic_raw;\n#endif\n\n#ifdef CLOCK_BOOTTIME\n    struct timespec boottime;\n#endif\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n    struct timespec process_cputime_id;\n#endif\n\n#ifdef CLOCK_THREAD_CPUTIME_ID\n    struct timespec thread_cputime_id;\n#endif\n\n    struct timespec clock_getcpuclockid;\n\n    struct timespec pthread_getcpuclockid;\n};\n\nvoid get_all_times(struct all_times *times)\n{\n    clockid_t clock;\n    struct timespec *spec;\n\n    memset(times, \'\\0\', sizeof(*times));\n\n    clock = CLOCK_REALTIME;\n    spec = &times->realtime;\n    clock_gettime(clock, spec);\n\n#ifdef CLOCK_REALTIME_COARSE\n    clock = CLOCK_REALTIME_COARSE;\n    spec = &times->realtime_coarse;\n    clock_gettime(clock, spec);\n#endif\n\n    clock = CLOCK_MONOTONIC;\n    spec = &times->monotonic;\n    clock_gettime(clock, spec);\n\n#ifdef CLOCK_MONOTONIC_COARSE\n    clock = CLOCK_MONOTONIC_COARSE;\n    spec = &times->monotonic_coarse;\n    clock_gettime(clock, spec);\n#endif\n\n#ifdef CLOCK_MONOTONIC_RAW\n    clock = CLOCK_MONOTONIC_RAW;\n    spec = &times->monotonic_raw;\n    clock_gettime(clock, spec);\n#endif\n\n#ifdef CLOCK_BOOTTIME\n    clock = CLOCK_BOOTTIME;\n    spec = &times->boottime;\n    clock_gettime(clock, spec);\n#endif\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n    clock = CLOCK_PROCESS_CPUTIME_ID;\n    spec = &times->process_cputime_id;\n    clock_gettime(clock, spec);\n#endif\n\n#ifdef CLOCK_THREAD_CPUTIME_ID\n    clock = CLOCK_THREAD_CPUTIME_ID;\n    spec = &times->thread_cputime_id;\n    clock_gettime(clock, spec);\n#endif\n\n    clock_getcpuclockid(0, &clock);\n    spec = &times->clock_getcpuclockid;\n    clock_gettime(clock, spec);\n\n    pthread_getcpuclockid(pthread_self(), &clock);\n    spec = &times->pthread_getcpuclockid;\n    clock_gettime(clock, spec);\n}\n\nvoid get_all_res(struct all_times *times)\n{\n    clockid_t clock;\n    struct timespec *spec;\n\n    memset(times, \'\\0\', sizeof(*times));\n\n    clock = CLOCK_REALTIME;\n    spec = &times->realtime;\n    clock_getres(clock, spec);\n\n#ifdef CLOCK_REALTIME_COARSE\n    clock = CLOCK_REALTIME_COARSE;\n    spec = &times->realtime_coarse;\n    clock_getres(clock, spec);\n#endif\n\n    clock = CLOCK_MONOTONIC;\n    spec = &times->monotonic;\n    clock_getres(clock, spec);\n\n#ifdef CLOCK_MONOTONIC_COARSE\n    clock = CLOCK_MONOTONIC_COARSE;\n    spec = &times->monotonic_coarse;\n    clock_getres(clock, spec);\n#endif\n\n#ifdef CLOCK_MONOTONIC_RAW\n    clock = CLOCK_MONOTONIC_RAW;\n    spec = &times->monotonic_raw;\n    clock_getres(clock, spec);\n#endif\n\n#ifdef CLOCK_BOOTTIME\n    clock = CLOCK_BOOTTIME;\n    spec = &times->boottime;\n    clock_getres(clock, spec);\n#endif\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n    clock = CLOCK_PROCESS_CPUTIME_ID;\n    spec = &times->process_cputime_id;\n    clock_getres(clock, spec);\n#endif\n\n#ifdef CLOCK_THREAD_CPUTIME_ID\n    clock = CLOCK_THREAD_CPUTIME_ID;\n    spec = &times->thread_cputime_id;\n    clock_getres(clock, spec);\n#endif\n\n    clock_getcpuclockid(0, &clock);\n    spec = &times->clock_getcpuclockid;\n    clock_getres(clock, spec);\n\n    pthread_getcpuclockid(pthread_self(), &clock);\n    spec = &times->pthread_getcpuclockid;\n    clock_getres(clock, spec);\n}\n\nvoid diff_time(const struct timespec *start, const struct timespec *end, struct timespec *diff)\n{\n    diff->tv_sec = end->tv_sec - start->tv_sec;\n    diff->tv_nsec = end->tv_nsec - start->tv_nsec;\n    if (diff->tv_nsec < 0)\n    {\n        diff->tv_nsec += 1000 * 1000 * 1000;\n        diff->tv_sec--;\n    }\n    assert (diff->tv_sec >= 0);\n    assert (diff->tv_nsec >= 0);\n}\n\nvoid diff_all_times(const struct all_times *start, const struct all_times *end, struct all_times *diff)\n{\n    diff_time(&start->realtime, &end->realtime, &diff->realtime);\n    diff_time(&start->realtime, &end->realtime, &diff->realtime);\n\n#ifdef CLOCK_REALTIME_COARSE\n    diff_time(&start->realtime_coarse, &end->realtime_coarse, &diff->realtime_coarse);\n#endif\n\n    diff_time(&start->monotonic, &end->monotonic, &diff->monotonic);\n\n#ifdef CLOCK_MONOTONIC_COARSE\n    diff_time(&start->monotonic_coarse, &end->monotonic_coarse, &diff->monotonic_coarse);\n#endif\n\n#ifdef CLOCK_MONOTONIC_RAW\n    diff_time(&start->monotonic_raw, &end->monotonic_raw, &diff->monotonic_raw);\n#endif\n\n#ifdef CLOCK_BOOTTIME\n    diff_time(&start->boottime, &end->boottime, &diff->boottime);\n#endif\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n    diff_time(&start->process_cputime_id, &end->process_cputime_id, &diff->process_cputime_id);\n#endif\n\n#ifdef CLOCK_THREAD_CPUTIME_ID\n    diff_time(&start->thread_cputime_id, &end->thread_cputime_id, &diff->thread_cputime_id);\n#endif\n\n    diff_time(&start->clock_getcpuclockid, &end->clock_getcpuclockid, &diff->clock_getcpuclockid);\n\n    diff_time(&start->pthread_getcpuclockid, &end->pthread_getcpuclockid, &diff->pthread_getcpuclockid);\n}\n\nvoid print_all_times(const struct all_times *start, const struct all_times *end, const struct all_times *diff, const struct all_times *res)\n{\n    printf("%-27s %15s %-9s %15s %-9s %5s %-9s %5s %-9s\\n", "clock", "", "start", "", "end", "", "diff", "", "res");\n\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_REALTIME", (long long)start->realtime.tv_sec, start->realtime.tv_nsec, (long long)end->realtime.tv_sec, end->realtime.tv_nsec, (long long)diff->realtime.tv_sec, diff->realtime.tv_nsec, (long long)res->realtime.tv_sec, res->realtime.tv_nsec);\n\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_REALTIME", (long long)start->realtime.tv_sec, start->realtime.tv_nsec, (long long)end->realtime.tv_sec, end->realtime.tv_nsec, (long long)diff->realtime.tv_sec, diff->realtime.tv_nsec, (long long)res->realtime.tv_sec, res->realtime.tv_nsec);\n\n#ifdef CLOCK_REALTIME_COARSE\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_REALTIME_COARSE", (long long)start->realtime_coarse.tv_sec, start->realtime_coarse.tv_nsec, (long long)end->realtime_coarse.tv_sec, end->realtime_coarse.tv_nsec, (long long)diff->realtime_coarse.tv_sec, diff->realtime_coarse.tv_nsec, (long long)res->realtime_coarse.tv_sec, res->realtime_coarse.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_REALTIME_COARSE");\n#endif\n\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_MONOTONIC", (long long)start->monotonic.tv_sec, start->monotonic.tv_nsec, (long long)end->monotonic.tv_sec, end->monotonic.tv_nsec, (long long)diff->monotonic.tv_sec, diff->monotonic.tv_nsec, (long long)res->monotonic.tv_sec, res->monotonic.tv_nsec);\n\n#ifdef CLOCK_MONOTONIC_COARSE\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_MONOTONIC_COARSE", (long long)start->monotonic_coarse.tv_sec, start->monotonic_coarse.tv_nsec, (long long)end->monotonic_coarse.tv_sec, end->monotonic_coarse.tv_nsec, (long long)diff->monotonic_coarse.tv_sec, diff->monotonic_coarse.tv_nsec, (long long)res->monotonic_coarse.tv_sec, res->monotonic_coarse.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_MONOTONIC_COARSE");\n#endif\n\n#ifdef CLOCK_MONOTONIC_RAW\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_MONOTONIC_RAW", (long long)start->monotonic_raw.tv_sec, start->monotonic_raw.tv_nsec, (long long)end->monotonic_raw.tv_sec, end->monotonic_raw.tv_nsec, (long long)diff->monotonic_raw.tv_sec, diff->monotonic_raw.tv_nsec, (long long)res->monotonic_raw.tv_sec, res->monotonic_raw.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_MONOTONIC_RAW");\n#endif\n\n#ifdef CLOCK_BOOTTIME\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_BOOTTIME", (long long)start->boottime.tv_sec, start->boottime.tv_nsec, (long long)end->boottime.tv_sec, end->boottime.tv_nsec, (long long)diff->boottime.tv_sec, diff->boottime.tv_nsec, (long long)res->boottime.tv_sec, res->boottime.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_BOOTTIME");\n#endif\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_PROCESS_CPUTIME_ID", (long long)start->process_cputime_id.tv_sec, start->process_cputime_id.tv_nsec, (long long)end->process_cputime_id.tv_sec, end->process_cputime_id.tv_nsec, (long long)diff->process_cputime_id.tv_sec, diff->process_cputime_id.tv_nsec, (long long)res->process_cputime_id.tv_sec, res->process_cputime_id.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_PROCESS_CPUTIME_ID");\n#endif\n\n#ifdef CLOCK_THREAD_CPUTIME_ID\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "CLOCK_THREAD_CPUTIME_ID", (long long)start->thread_cputime_id.tv_sec, start->thread_cputime_id.tv_nsec, (long long)end->thread_cputime_id.tv_sec, end->thread_cputime_id.tv_nsec, (long long)diff->thread_cputime_id.tv_sec, diff->thread_cputime_id.tv_nsec, (long long)res->thread_cputime_id.tv_sec, res->thread_cputime_id.tv_nsec);\n#else\n    printf("%-27s (not available)\\n", "CLOCK_THREAD_CPUTIME_ID");\n#endif\n\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "clock_getcpuclockid", (long long)start->clock_getcpuclockid.tv_sec, start->clock_getcpuclockid.tv_nsec, (long long)end->clock_getcpuclockid.tv_sec, end->clock_getcpuclockid.tv_nsec, (long long)diff->clock_getcpuclockid.tv_sec, diff->clock_getcpuclockid.tv_nsec, (long long)res->clock_getcpuclockid.tv_sec, res->clock_getcpuclockid.tv_nsec);\n\n    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ld\\n", "pthread_getcpuclockid", (long long)start->pthread_getcpuclockid.tv_sec, start->pthread_getcpuclockid.tv_nsec, (long long)end->pthread_getcpuclockid.tv_sec, end->pthread_getcpuclockid.tv_nsec, (long long)diff->pthread_getcpuclockid.tv_sec, diff->pthread_getcpuclockid.tv_nsec, (long long)res->pthread_getcpuclockid.tv_sec, res->pthread_getcpuclockid.tv_nsec);\n}\n\nvoid signal_handler(int sig)\n{\n    (void)sig;\n    /*\n        We don\'t actually need to do anything, just the presence of the\n        signal handler is enough to make `clock_nanosleep` return.\n\n        However, because somebody requested that we stop, we *should*\n        listen to them and actually stop.\n    */\n    raise(SIGSTOP);\n}\n\nvoid do_sleep(struct timespec *total)\n{\n    int not_errno;\n    struct sigaction act;\n    memset(&act, \'\\0\', sizeof(act));\n    act.sa_handler = signal_handler;\n    /* TODO - it is impossible to catch SIGSTOP, is there another way? */\n    sigaction(SIGTSTP, &act, NULL);\n    sigaction(SIGTTIN, &act, NULL);\n    sigaction(SIGTTOU, &act, NULL);\n    /*\n        Note: synchronous methods of signal handling do *not* work here.\n        The `clock_nanosleep` will just resume silently in that case.\n        Using `sigtimedwait` does not directly give is a `remain` value.\n    */\n    do\n    {\n        /* Important note: clock_nanosleep does *not* use `errno`. */\n        not_errno = clock_nanosleep(CLOCK_MONOTONIC, 0, total, total);\n    }\n    while (not_errno == EINTR);\n}\n\n\n\nstatic void die(const char *msg)\n{\n    printf("%s\\n", msg);\n    exit(1);\n}\n\nstatic void parse_time(char *str, struct timespec *spec)\n{\n    unsigned long long sec, nsec, multiplier;\n    char *end;\n    if (!isdigit(str[0]))\n    {\n        die("Non-numeric character at start of duration.");\n    }\n    errno = 0;\n    sec = strtoull(str, &end, 10);\n    spec->tv_sec = sec;\n    if (errno || (unsigned long long)spec->tv_sec != sec)\n    {\n        die("Out-of-range duration.");\n    }\n    if (*end == \'\\0\')\n    {\n        spec->tv_nsec = 0;\n        return;\n    }\n    if (*end != \'.\')\n    {\n        die("Non-numeric character in duration.");\n    }\n    ++end;\n    multiplier = 100 * 1000 * 1000;\n    nsec = 0;\n    while (*end)\n    {\n        unsigned long long digit = *end - \'0\';\n        if (digit >= 10)\n        {\n            die("Non-numeric character in fractional duration.");\n        }\n        nsec += multiplier * digit;\n        multiplier /= 10;\n        ++end;\n        /* TODO instead of truncating extra precision, round up? */\n    }\n    spec->tv_nsec = nsec;\n}\n\nint main(int argc, char **argv)\n{\n    struct timespec total;\n    struct all_times start, end, diff, res;\n\n    if (argc != 2 || argv[1][0] == \'-\')\n    {\n        die("Usage: ./nanosleep sss[.mmmuuunnn]");\n    }\n    parse_time(argv[1], &total);\n\n    get_all_res(&res);\n    get_all_times(&start);\n    do_sleep(&total);\n    get_all_times(&end);\n\n    diff_all_times(&start, &end, &diff);\n    print_all_times(&start, &end, &diff, &res);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
$ ./nanosleep 1.2\nclock                                       start                     end             diff            res      \nCLOCK_REALTIME                   1461281943.302055558      1461281944.502279160     1.200223602     0.000000001\nCLOCK_REALTIME                   1461281943.302055558      1461281944.502279160     1.200223602     0.000000001\nCLOCK_REALTIME_COARSE            1461281943.299600851      1461281944.499668121     1.200067270     0.004000000\nCLOCK_MONOTONIC                      130817.112863848          130818.313087604     1.200223756     0.000000001\nCLOCK_MONOTONIC_COARSE               130817.110408795          130818.310476065     1.200067270     0.004000000\nCLOCK_MONOTONIC_RAW                  130809.723951252          130810.924108013     1.200156761     0.000000001\nCLOCK_BOOTTIME                       198571.683842245          198572.884067547     1.200225302     0.000000001\nCLOCK_PROCESS_CPUTIME_ID                  0.002856240               0.002900410     0.000044170     0.000000001\nCLOCK_THREAD_CPUTIME_ID                   0.002857132               0.002903159     0.000046027     0.000000001\nclock_getcpuclockid                       0.002857981               0.002905128     0.000047147     0.000000001\npthread_getcpuclockid                     0.002858526               0.002908051     0.000049525     0.000000001\n
Run Code Online (Sandbox Code Playgroud)\n