如何暂停然后恢复“睡眠”调用

时间:2016-04-21 03:38:45

标签: c linux bash time sleep

调用sleep(10)表示睡眠指定的秒数。当我键入“sleep 10”时,我想等待10秒但是当我在睡眠命令后立即使用CTRL-Z(或发送SIGTSTP)时,它不会停止“计时器”(或计数器)尽管这个过程已经停止了。

我可以通过jobs看到sleep的状态已更改为STOPPED,但如果我等待10秒然后将此流程发送到前台,它将立即完成,即使它运行不到10秒。

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

更新 ::我现在明白睡眠是使用挂钟时间,所以如何用用户cpu时间实现睡眠

3 个答案:

答案 0 :(得分:1)

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

clock_nanosleep还有一个优点,即允许您指定要睡觉的时钟类型 - 至少有7个不同的时钟,每个时钟在不同情况下都有用。你有可能想要CLOCK_MONOTONIC。 (注意你在睡觉时使用没有 CPU时间,所以你绝对不想要CLOCK_PROCESS_CPUTIME_ID(这在多线程进程中会有意义))

引用后一个手册页:

   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.

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

/*
    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

答案 1 :(得分:-1)

抱歉,我不知道正确的解决方案。 但我有一个想法,我希望能帮到你。

如果代码低于

{
    ...
    sleep(10);
    ...
}

代码可能会成为三部分。 示例代码如下:

{//change code
    ...
    sleep_thread();
    mutex_lock(&sleep_mutex);
    ...
}

{//sleep thread
    mutex_lock(&sleep_mutex);
    sleep(10);
    mutex_unlock(&sleep_mutex);
}

{//handle signal
    if(receive_signal == SIGUSR)
        mutex_unlock(&sleep_mutex);
}

答案 2 :(得分:-1)

如果你输入“ctrl + c”,也许你可以尝试如下:

void signal_fun(int singal)
{
    printf("This is signal fun\n");
}

int main(int argc, char* argv[])
{
    signal(SIGINT, signal_fun);
    sleep(10);
    printf("This is main fun\n");

    exit(EXIT_SUCCESS);
}