c-我怎样才能暂停然后继续呼叫“睡眠”



调用sleep(10)意味着睡眠指定的秒数。当我键入"sleep 10"时,我想等待10秒,但当我在sleep命令后立即使用CTRL-Z(或发送SIGTSTP)时,即使进程已经停止,它也不会停止"计时器"(或计数器)。

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

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

更新::我现在知道睡眠使用的是墙上的时钟时间,那么我如何使用用户cpu时间实现睡眠

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

clock_nanosleep还有一个优点,可以让你指定你想用什么样的时钟睡觉——至少有7个不同的时钟,每个时钟在不同的情况下都很有用。不过,你很可能想要CLOCK_MONOTONIC。(请注意,您在睡眠时使用noCPU时间,所以您肯定不想要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, '', 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, '', 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 %-9sn", "clock", "", "start", "", "end", "", "diff", "", "res");
    printf("%-27s %15lld.%09ld %15lld.%09ld %5lld.%09ld %5lld.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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.%09ldn", "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, '', 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("%sn", 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 == '')
    {
        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(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);
}

如果您输入"ctrl+c",也许您可以尝试以下操作:

void signal_fun(int singal)
{
    printf("This is signal funn");
}
int main(int argc, char* argv[])
{
    signal(SIGINT, signal_fun);
    sleep(10);
    printf("This is main funn");
    exit(EXIT_SUCCESS);
}

最新更新