调用sleep(10)
意味着睡眠指定的秒数。 当我input“睡眠10”时,我想等待10秒钟,但是当我在睡眠命令之后立即使用CTRL-Z(或发送SIGTSTP
)时,它不会停止“定时器”(或计数器),即使进程已经停止。
我可以通过jobs
看到sleep
已经改变为STOPPED
但是如果我等待10秒,然后将这个过程发送到前台,它将立即完成 ,即使它运行的时间less于10秒。
所以,我的问题是如何停止睡眠定时器运行?
更新 ::我现在明白,睡眠是使用挂钟时间,所以我怎么能用一个用户cpu时间来实现睡眠
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 = ×->realtime; clock_gettime(clock, spec); #ifdef CLOCK_REALTIME_COARSE clock = CLOCK_REALTIME_COARSE; spec = ×->realtime_coarse; clock_gettime(clock, spec); #endif clock = CLOCK_MONOTONIC; spec = ×->monotonic; clock_gettime(clock, spec); #ifdef CLOCK_MONOTONIC_COARSE clock = CLOCK_MONOTONIC_COARSE; spec = ×->monotonic_coarse; clock_gettime(clock, spec); #endif #ifdef CLOCK_MONOTONIC_RAW clock = CLOCK_MONOTONIC_RAW; spec = ×->monotonic_raw; clock_gettime(clock, spec); #endif #ifdef CLOCK_BOOTTIME clock = CLOCK_BOOTTIME; spec = ×->boottime; clock_gettime(clock, spec); #endif #ifdef CLOCK_PROCESS_CPUTIME_ID clock = CLOCK_PROCESS_CPUTIME_ID; spec = ×->process_cputime_id; clock_gettime(clock, spec); #endif #ifdef CLOCK_THREAD_CPUTIME_ID clock = CLOCK_THREAD_CPUTIME_ID; spec = ×->thread_cputime_id; clock_gettime(clock, spec); #endif clock_getcpuclockid(0, &clock); spec = ×->clock_getcpuclockid; clock_gettime(clock, spec); pthread_getcpuclockid(pthread_self(), &clock); spec = ×->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 = ×->realtime; clock_getres(clock, spec); #ifdef CLOCK_REALTIME_COARSE clock = CLOCK_REALTIME_COARSE; spec = ×->realtime_coarse; clock_getres(clock, spec); #endif clock = CLOCK_MONOTONIC; spec = ×->monotonic; clock_getres(clock, spec); #ifdef CLOCK_MONOTONIC_COARSE clock = CLOCK_MONOTONIC_COARSE; spec = ×->monotonic_coarse; clock_getres(clock, spec); #endif #ifdef CLOCK_MONOTONIC_RAW clock = CLOCK_MONOTONIC_RAW; spec = ×->monotonic_raw; clock_getres(clock, spec); #endif #ifdef CLOCK_BOOTTIME clock = CLOCK_BOOTTIME; spec = ×->boottime; clock_getres(clock, spec); #endif #ifdef CLOCK_PROCESS_CPUTIME_ID clock = CLOCK_PROCESS_CPUTIME_ID; spec = ×->process_cputime_id; clock_getres(clock, spec); #endif #ifdef CLOCK_THREAD_CPUTIME_ID clock = CLOCK_THREAD_CPUTIME_ID; spec = ×->thread_cputime_id; clock_getres(clock, spec); #endif clock_getcpuclockid(0, &clock); spec = ×->clock_getcpuclockid; clock_getres(clock, spec); pthread_getcpuclockid(pthread_self(), &clock); spec = ×->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(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 fun\n"); } int main(int argc, char* argv[]) { signal(SIGINT, signal_fun); sleep(10); printf("This is main fun\n"); exit(EXIT_SUCCESS); }