我怎么可以暂停,然后恢复到`sleep`通话 [英] how can I pause and then resume a call to `sleep`

查看:358
本文介绍了我怎么可以暂停,然后恢复到`sleep`通话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

调用睡眠(10)指睡眠中指定的秒数。当我输入休眠10我想,以等待10秒钟,但是当我使用CTRL-Z(或发送 SIGTSTP )休眠指令之后,它不会停止计时器(或柜台),即使该进程已停止。

Calling sleep(10) means to sleep for the specified number of seconds. When I type "sleep 10" I suppose to wait 10 seconds but when I'm using CTRL-Z (or sending SIGTSTP) right after sleep command, it won't stop the "timer" (or the counter) even though that the process has stopped.

我可以通过职位见的状态睡眠已更改为结束,但如果我会等待10秒钟,然后把这个过程推到前台,将完成立即,即使它跑不到10秒。

I can see via jobs that the status of sleep has changed to STOPPED but if I'll wait 10 seconds and then send this process to the foreground it will finish immediately, even though it run less then 10 seconds.

所以,我的问题是我怎么能停止运行睡眠定时器?

So, my question is how can I stop sleep timer from running??

更新 ::我现在明白了,睡眠是使用挂钟时间,所以我怎么能实现睡眠与用户的CPU时间

Update:: I Understand now that sleep is using wall-clock time, so how can I implement sleep with a user cpu time

推荐答案

睡眠(3) 返回剩余的,如果它是由一个信号中断的秒数,而是以秒为粒度差,所以最好使用的 clock_nanosleep(2)

clock_nanosleep 还允许你指定你想要睡觉什么样的时钟的优势 - 至少有7种不同的时钟,在不同情况下每个有用的。有可能到头来你想要 CLOCK_MONOTONIC 虽然。 (请注意,您使用的没有的CPU时间睡觉,所以你绝对不希望 CLOCK_PROCESS_CPUTIME_ID (这将是一个多线程进程有意义))

clock_nanosleep also has the advantage of allowing you to specify what kind of clock you want to sleep with - there are at least 7 different clocks, each useful in different circumstances. Chances are you want CLOCK_MONOTONIC though. (Note that you use no CPU time while sleeping, so you definitely don't want CLOCK_PROCESS_CPUTIME_ID (it would be meaningful in a multithreaded process))

引用后者手册页:

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

编辑:最后我写一个程序演示,你需要做什么,以及各时钟之间的区别:

I ended up writing a program demonstrating what you need to do, as well as the difference between the various clocks:

/*
    Requires adding
        -pthread -lrt
    to your command line.
 */
#define _POSIX_C_SOURCE 200112L

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

struct all_times
{
    struct timespec realtime;

#ifdef CLOCK_REALTIME_COARSE
    struct timespec realtime_coarse;
#endif

    struct timespec monotonic;

#ifdef CLOCK_MONOTONIC_COARSE
    struct timespec monotonic_coarse;
#endif

#ifdef CLOCK_MONOTONIC_RAW
    struct timespec monotonic_raw;
#endif

#ifdef CLOCK_BOOTTIME
    struct timespec boottime;
#endif

#ifdef CLOCK_PROCESS_CPUTIME_ID
    struct timespec process_cputime_id;
#endif

#ifdef CLOCK_THREAD_CPUTIME_ID
    struct timespec thread_cputime_id;
#endif

    struct timespec clock_getcpuclockid;

    struct timespec pthread_getcpuclockid;
};

void get_all_times(struct all_times *times)
{
    clockid_t clock;
    struct timespec *spec;

    memset(times, '\0', sizeof(*times));

    clock = CLOCK_REALTIME;
    spec = &times->realtime;
    clock_gettime(clock, spec);

#ifdef CLOCK_REALTIME_COARSE
    clock = CLOCK_REALTIME_COARSE;
    spec = &times->realtime_coarse;
    clock_gettime(clock, spec);
#endif

    clock = CLOCK_MONOTONIC;
    spec = &times->monotonic;
    clock_gettime(clock, spec);

#ifdef CLOCK_MONOTONIC_COARSE
    clock = CLOCK_MONOTONIC_COARSE;
    spec = &times->monotonic_coarse;
    clock_gettime(clock, spec);
#endif

#ifdef CLOCK_MONOTONIC_RAW
    clock = CLOCK_MONOTONIC_RAW;
    spec = &times->monotonic_raw;
    clock_gettime(clock, spec);
#endif

#ifdef CLOCK_BOOTTIME
    clock = CLOCK_BOOTTIME;
    spec = &times->boottime;
    clock_gettime(clock, spec);
#endif

#ifdef CLOCK_PROCESS_CPUTIME_ID
    clock = CLOCK_PROCESS_CPUTIME_ID;
    spec = &times->process_cputime_id;
    clock_gettime(clock, spec);
#endif

#ifdef CLOCK_THREAD_CPUTIME_ID
    clock = CLOCK_THREAD_CPUTIME_ID;
    spec = &times->thread_cputime_id;
    clock_gettime(clock, spec);
#endif

    clock_getcpuclockid(0, &clock);
    spec = &times->clock_getcpuclockid;
    clock_gettime(clock, spec);

    pthread_getcpuclockid(pthread_self(), &clock);
    spec = &times->pthread_getcpuclockid;
    clock_gettime(clock, spec);
}

void get_all_res(struct all_times *times)
{
    clockid_t clock;
    struct timespec *spec;

    memset(times, '\0', sizeof(*times));

    clock = CLOCK_REALTIME;
    spec = &times->realtime;
    clock_getres(clock, spec);

#ifdef CLOCK_REALTIME_COARSE
    clock = CLOCK_REALTIME_COARSE;
    spec = &times->realtime_coarse;
    clock_getres(clock, spec);
#endif

    clock = CLOCK_MONOTONIC;
    spec = &times->monotonic;
    clock_getres(clock, spec);

#ifdef CLOCK_MONOTONIC_COARSE
    clock = CLOCK_MONOTONIC_COARSE;
    spec = &times->monotonic_coarse;
    clock_getres(clock, spec);
#endif

#ifdef CLOCK_MONOTONIC_RAW
    clock = CLOCK_MONOTONIC_RAW;
    spec = &times->monotonic_raw;
    clock_getres(clock, spec);
#endif

#ifdef CLOCK_BOOTTIME
    clock = CLOCK_BOOTTIME;
    spec = &times->boottime;
    clock_getres(clock, spec);
#endif

#ifdef CLOCK_PROCESS_CPUTIME_ID
    clock = CLOCK_PROCESS_CPUTIME_ID;
    spec = &times->process_cputime_id;
    clock_getres(clock, spec);
#endif

#ifdef CLOCK_THREAD_CPUTIME_ID
    clock = CLOCK_THREAD_CPUTIME_ID;
    spec = &times->thread_cputime_id;
    clock_getres(clock, spec);
#endif

    clock_getcpuclockid(0, &clock);
    spec = &times->clock_getcpuclockid;
    clock_getres(clock, spec);

    pthread_getcpuclockid(pthread_self(), &clock);
    spec = &times->pthread_getcpuclockid;
    clock_getres(clock, spec);
}

void diff_time(const struct timespec *start, const struct timespec *end, struct timespec *diff)
{
    diff->tv_sec = end->tv_sec - start->tv_sec;
    diff->tv_nsec = end->tv_nsec - start->tv_nsec;
    if (diff->tv_nsec < 0)
    {
        diff->tv_nsec += 1000 * 1000 * 1000;
        diff->tv_sec--;
    }
    assert (diff->tv_sec >= 0);
    assert (diff->tv_nsec >= 0);
}

void diff_all_times(const struct all_times *start, const struct all_times *end, struct all_times *diff)
{
    diff_time(&start->realtime, &end->realtime, &diff->realtime);
    diff_time(&start->realtime, &end->realtime, &diff->realtime);

#ifdef CLOCK_REALTIME_COARSE
    diff_time(&start->realtime_coarse, &end->realtime_coarse, &diff->realtime_coarse);
#endif

    diff_time(&start->monotonic, &end->monotonic, &diff->monotonic);

#ifdef CLOCK_MONOTONIC_COARSE
    diff_time(&start->monotonic_coarse, &end->monotonic_coarse, &diff->monotonic_coarse);
#endif

#ifdef CLOCK_MONOTONIC_RAW
    diff_time(&start->monotonic_raw, &end->monotonic_raw, &diff->monotonic_raw);
#endif

#ifdef CLOCK_BOOTTIME
    diff_time(&start->boottime, &end->boottime, &diff->boottime);
#endif

#ifdef CLOCK_PROCESS_CPUTIME_ID
    diff_time(&start->process_cputime_id, &end->process_cputime_id, &diff->process_cputime_id);
#endif

#ifdef CLOCK_THREAD_CPUTIME_ID
    diff_time(&start->thread_cputime_id, &end->thread_cputime_id, &diff->thread_cputime_id);
#endif

    diff_time(&start->clock_getcpuclockid, &end->clock_getcpuclockid, &diff->clock_getcpuclockid);

    diff_time(&start->pthread_getcpuclockid, &end->pthread_getcpuclockid, &diff->pthread_getcpuclockid);
}

void print_all_times(const struct all_times *start, const struct all_times *end, const struct all_times *diff, const struct all_times *res)
{
    printf("%-27s %15s %-9s %15s %-9s %5s %-9s %5s %-9s\n", "clock", "", "start", "", "end", "", "diff", "", "res");

    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);

    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);

#ifdef CLOCK_REALTIME_COARSE
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_REALTIME_COARSE");
#endif

    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);

#ifdef CLOCK_MONOTONIC_COARSE
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_MONOTONIC_COARSE");
#endif

#ifdef CLOCK_MONOTONIC_RAW
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_MONOTONIC_RAW");
#endif

#ifdef CLOCK_BOOTTIME
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_BOOTTIME");
#endif

#ifdef CLOCK_PROCESS_CPUTIME_ID
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_PROCESS_CPUTIME_ID");
#endif

#ifdef CLOCK_THREAD_CPUTIME_ID
    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);
#else
    printf("%-27s (not available)\n", "CLOCK_THREAD_CPUTIME_ID");
#endif

    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);

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

void signal_handler(int sig)
{
    (void)sig;
    /*
        We don't actually need to do anything, just the presence of the
        signal handler is enough to make `clock_nanosleep` return.

        However, because somebody requested that we stop, we *should*
        listen to them and actually stop.
    */
    raise(SIGSTOP);
}

void do_sleep(struct timespec *total)
{
    int not_errno;
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_handler = signal_handler;
    /* TODO - it is impossible to catch SIGSTOP, is there another way? */
    sigaction(SIGTSTP, &act, NULL);
    sigaction(SIGTTIN, &act, NULL);
    sigaction(SIGTTOU, &act, NULL);
    /*
        Note: synchronous methods of signal handling do *not* work here.
        The `clock_nanosleep` will just resume silently in that case.
        Using `sigtimedwait` does not directly give is a `remain` value.
    */
    do
    {
        /* Important note: clock_nanosleep does *not* use `errno`. */
        not_errno = clock_nanosleep(CLOCK_MONOTONIC, 0, total, total);
    }
    while (not_errno == EINTR);
}



static void die(const char *msg)
{
    printf("%s\n", msg);
    exit(1);
}

static void parse_time(char *str, struct timespec *spec)
{
    unsigned long long sec, nsec, multiplier;
    char *end;
    if (!isdigit(str[0]))
    {
        die("Non-numeric character at start of duration.");
    }
    errno = 0;
    sec = strtoull(str, &end, 10);
    spec->tv_sec = sec;
    if (errno || (unsigned long long)spec->tv_sec != sec)
    {
        die("Out-of-range duration.");
    }
    if (*end == '\0')
    {
        spec->tv_nsec = 0;
        return;
    }
    if (*end != '.')
    {
        die("Non-numeric character in duration.");
    }
    ++end;
    multiplier = 100 * 1000 * 1000;
    nsec = 0;
    while (*end)
    {
        unsigned long long digit = *end - '0';
        if (digit >= 10)
        {
            die("Non-numeric character in fractional duration.");
        }
        nsec += multiplier * digit;
        multiplier /= 10;
        ++end;
        /* TODO instead of truncating extra precision, round up? */
    }
    spec->tv_nsec = nsec;
}

int main(int argc, char **argv)
{
    struct timespec total;
    struct all_times start, end, diff, res;

    if (argc != 2 || argv[1][0] == '-')
    {
        die("Usage: ./nanosleep sss[.mmmuuunnn]");
    }
    parse_time(argv[1], &total);

    get_all_res(&res);
    get_all_times(&start);
    do_sleep(&total);
    get_all_times(&end);

    diff_all_times(&start, &end, &diff);
    print_all_times(&start, &end, &diff, &res);
    return 0;
}

输出:

$ ./nanosleep 1.2
clock                                       start                     end             diff            res      
CLOCK_REALTIME                   1461281943.302055558      1461281944.502279160     1.200223602     0.000000001
CLOCK_REALTIME                   1461281943.302055558      1461281944.502279160     1.200223602     0.000000001
CLOCK_REALTIME_COARSE            1461281943.299600851      1461281944.499668121     1.200067270     0.004000000
CLOCK_MONOTONIC                      130817.112863848          130818.313087604     1.200223756     0.000000001
CLOCK_MONOTONIC_COARSE               130817.110408795          130818.310476065     1.200067270     0.004000000
CLOCK_MONOTONIC_RAW                  130809.723951252          130810.924108013     1.200156761     0.000000001
CLOCK_BOOTTIME                       198571.683842245          198572.884067547     1.200225302     0.000000001
CLOCK_PROCESS_CPUTIME_ID                  0.002856240               0.002900410     0.000044170     0.000000001
CLOCK_THREAD_CPUTIME_ID                   0.002857132               0.002903159     0.000046027     0.000000001
clock_getcpuclockid                       0.002857981               0.002905128     0.000047147     0.000000001
pthread_getcpuclockid                     0.002858526               0.002908051     0.000049525     0.000000001

这篇关于我怎么可以暂停,然后恢复到`sleep`通话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆