定时器API
函数定义
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); /* 创建定时器 */
int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value,struct itimerspec *old_value); /* 初始化定时器 */
int timer_gettime(timer_t timerid,struct itimerspec *value); /* 获得一个活动定时器的剩余时间 */
int timer_delete(timer_t timerid); /* 删除定时器 */
参数介绍
clockid_t clock_id
有如下几种选择。
CLOCK_REALTIME /* Systemwide realtime clock. 一个可设置的系统范围内的实时时钟,计算从1970年1月1日午夜0点起的毫秒数 */
CLOCK_MONOTONIC /* Represents monotonic time. Cannot be set. 一个不可设置的单调增加时钟,它测度系统启动后某个非特定时间点起的时间 */
CLOCK_PROCESS_CPUTIME_ID /* High resolution per-process timer. 这个时钟测量调用进程(包含其中所有线程)所消耗的 (用户和系统) CPU 时间 */
CLOCK_THREAD_CPUTIME_ID /* Thread-specific timer. 这个时钟测量调用线程所消耗的 (用户和系统) CPU 时间*/
CLOCK_REALTIME_HR /* High resolution version of CLOCK_REALTIME. */
CLOCK_MONOTONIC_HR /* High resolution version of CLOCK_MONOTONIC. */
参数 struct sigevent *evp
定义计时器到期时,调用者应如何被通知这个事件。
SIGEV_NONE /* 当计时器到期不进行异步通知 */
SIGEV_SIGNAL /* 到计时器到期时,在进程中产生信号量 sigev_signo */
SIGEV_THREAD /* 到计时器到期时,调用 sigev_notify_function 好像它是一个新线程的启动函数 */
SIGEV_THREAD_ID /* 类似 SIGEV_SIGNAL,但信号量signal 针对由 sigev_notify_thread_id 指定的线程,这个线程必须和调用线程在同一个进程中 */
实例
#include <dlfcn.h>
#include <errno.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <pthread.h>
timer_t g_timer = NULL;
#define TIMEOUT_DEFAULT_VALUE 1 * 60 /* 1分钟 */
static int timer_setup();
static int timer_destroy();
static int timer_run(unsigned int timeout);
/* 格式化时间字符串格式为:Www Mmm dd hh:mm:ss yyyy */
void ctime_get_time(char *string)
{
time_t t;
time(&t);
printf("%s --%s\n", string, ctime(&t)); /* 打印的是当前时区的时间 */
}
static void timeout_handler()
{
ctime_get_time("timeout_handler");
timer_destroy();
}
/* 创建定时器 */
static int timer_setup()
{
int retval;
timer_t timer;
struct sigaction act;
struct sigevent evp;
memset(&act, 0, sizeof(act));
act.sa_handler = timeout_handler; /* 倒计时结束的时候调用的函数 */
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
if (sigaction(SIGUSR2, &act, NULL) == -1) {
return -1;
}
memset(&evp, 0, sizeof(evp));
evp.sigev_value.sival_ptr = &timer;
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGUSR2;
retval = timer_create(CLOCK_REALTIME, &evp, &timer);
if (retval != 0) {
return -2;
}
g_timer = timer;
ctime_get_time("timer_setup");
return 0;
}
/* 销毁定时器 */
static int timer_destroy()
{
int retval = 0;
if (g_timer != NULL) {
retval = timer_delete(g_timer);
g_timer = NULL;
}
return retval;
}
/* 启动定时器 */
static int timer_run(unsigned int seconds)
{
int retval;
struct itimerspec ts;
if (g_timer == NULL) {
timer_setup();
}
ts.it_value.tv_sec = seconds; /* 倒计时的时间 */
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
retval = timer_settime(g_timer, 0, &ts, NULL);
if (retval != 0) {
return -1;
}
return 0;
}
static void *thread_time(void *data)
{
printf("thread_time enter\n");
timer_setup();
timer_run(TIMEOUT_DEFAULT_VALUE);
}
int main(int argc, char const *argv[])
{
pthread_t pid;
pthread_create(&pid, NULL, thread_time, NULL);
pthread_join(pid, NULL);
while(1);
return 0;
}
代码逻辑
创建一个线程thread_time来创建和设定定时器,设定一分钟,到期调用timeout_handler
执行结果
thread_time enter
timer_setup --Sat May 30 16:39:25 2020
timeout_handler --Sat May 30 16:40:25 2020
PS
创建定时器后与系统时间就没有关系了,假如设定16:39:25开始计时后,修改系统时间到16:40:25,并不会触发定时器结束,一定是等到定时的一分钟到达后,才会触发定时器结束。