调用sleep(10)
表示睡眠指定的秒数。当我键入“sleep 10”时,我想等待10秒但是当我在睡眠命令后立即使用CTRL-Z(或发送SIGTSTP
)时,它不会停止“计时器”(或计数器)尽管这个过程已经停止了。
我可以通过jobs
看到sleep
的状态已更改为STOPPED
,但如果我等待10秒然后将此流程发送到前台,它将立即完成,即使它运行不到10秒。
所以,我的问题是如何停止睡眠计时器的运行?
更新 ::我现在明白睡眠是使用挂钟时间,所以如何用用户cpu时间实现睡眠
答案 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 = ×->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
答案 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);
}