POSIX定时器使用方法

定时器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,并不会触发定时器结束,一定是等到定时的一分钟到达后,才会触发定时器结束。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值