0
点赞
收藏
分享

微信扫一扫

Linux中Posix定时器的使用

何以至千里 2021-09-25 阅读 61

在上一节已经了解到Linux上使用各种定时器的优缺点,接下来主要介绍Posix定时器。
传送门:关于Linux应用层的定时器

posix定时器还是比较简单的,主要就在于学习API的使用。

API接口详细说明

  • int timer_create(clockid_t clockid, struct sigevent *sevp,timer_t timerid)

参数 必选 类型 说明
clock_id ture IN 说明定时器是基于哪个时钟的,可有以下取值:
1. CLOCK_REALTIME :Systemwide realtime clock.(系统实时时间,即日历时间)
2. CLOCK_MONOTONIC:Represents monotonic time. Cannot be set.(从系统启动开始到现在为止的时间)
3.CLOCK_PROCESS_CPUTIME_ID :High resolution per-process timer(本进程启动到执行到当前代码,系统CPU花费的时间).
4. CLOCK_THREAD_CPUTIME_ID :Thread-specific timer(本线程启动到执行到当前代码,系统CPU花费的时间).
5.CLOCK_REALTIME_HR :High resolution version of CLOCK_REALTIME(CLOCK_REALTIME的细粒度(高精度)版本).
6.CLOCK_MONOTONIC_HR :High resolution version of CLOCK_MONOTONIC(CLOCK_MONOTONIC的细粒度版本).
*sevp true IN 设置了定时器到期时的通知方式和处理方式(结构体详细定义参见下方)
该类型结构体使用前要初始化(memset等), 否则可能出现timer到期无动作的异常情况.
*timerid true OUT 创建的timer的id 通过这个指针返回.
返回值 true OUT On success,return 0.On error,-1 is returned,and errno is set to indicate the error.


  • int timer_delete (timer_t timerid)

参数 必选 类型 说明
timerid true IN 指定的timer
返回值 true OUT On success,return 0.On error,-1 is returned,and errno is set to indicate the error.


  • int timer_settime(timer_t timerid, int flags,const struct itimerspec *new_value,struct itimerspec *old_value)

参数 必选 类型 说明
timerid true IN 指定的timer
flags true IN 0 :new_value->it_value 表示希望timer首次到期时的时间与启动timer的时间间隔.
TIMER_ABSTIME:new_value->it_value 表示希望timer首次到期的绝对时间.
(如果new_value->it_value 设定的绝对时间 早于 当前的绝对时间, 那么timer会立即到期.)
(如果时钟 CLOCK_REALTIME 被调整了,那么timer的首次过期时间也会适当调整.)
new_value true IN new_value 有2个子域: it_value 和 it_interval
⑴ it_value : 用于设置首次timer到期的时间, 也是 启动/停止 timer的控制域;
⑵ it_interval : 用于设置timer循环的时间间隔, 如果其值不为0(秒和纳秒至少有一个不为0),每次timer到期时,timer会使用new_value->it_interval的值重新加载timer;
如果其值为0, timer只会在it_value指定的时间到期一次,之后不会重新加载timer.
①启动timer:
前提:timer处于停止(disarmed)状态,否则就是重置timer.
设置:new_value->it_value的值是非0值(秒和纳秒都不等于0或者其中一个不等于0).
结果:timer变为启动(armed)状态.
② 停止timer:
设置:new_value->it_value的的值为0(秒和纳秒都为0).
结果:timer变为停止(disarmed)状态.
③重置timer:
前提:timer处于已启动(armed)状态,否则就是启动timer
设置:new_value->it_value的的值不为0(秒和纳秒至少有一个不为0)
结果:timer仍为(armed)状态.之前的参数(即new_value(it_value 和 it_interval))设置会被覆盖.
old_value true OUT 取得上一次的设置的new_value
返回值 true OUT On success,return 0.On error,-1 is returned,and errno is set to indicate the error.


  • int timer_gettime(timer_t timerid, struct itimerspec *curr_value)

参数 必选 类型 说明
timerid true IN 指定的timer
curr_value true OUT curr_value->it_value : 离timer到期的剩余时间
curr_value->it_interval : timer的循环时间间隔
返回值 true OUT On success,return 0.On error,-1 is returned,and errno is set to indicate the error.


  • int timer_getoverrun(timer_t timerid)

参数 必选 类型 说明
timerid true IN 指定的timer
返回值 true OUT On success,return 0.On error,-1 is returned,and errno is set to indicate the error.


结构体定义说明:

. struct sigevent结构的定义如下:

struct sigevent
{
int sigev_notify; //设置定时器到期后的行为
int sigev_signo; //设置产生信号的信号码
union sigval sigev_value; //设置产生信号的值
void (*sigev_notify_function)(union sigval);//定时器到期,从该地址启动一个线程
pthread_attr_t *sigev_notify_attributes; //创建线程的属性
}

union sigval
{
int sival_int; //integer value
void *sival_ptr; //pointer value
}

如果sevp传入NULL,那么定时器到期会产生默认的信号,对CLOCK_REALTIMER来说,默认信号就是SIGALRM,如果要产生除默认信号之外的其他信号,程序必须将evp->sigev_signo设置为期望的信号码。
sigev_notify:的值可取以下几种:

  • SIGEV_NONE:定时器到期后什么都不做,只提供通过timer_gettime和timer_getoverrun查询超时信息。
  • SIGEV_SIGNAL:定时器到期后,内核会将sigev_signo所指定的信号,传送给进程,在信号处理程序中,si_value会被设定为sigev_value的值。
  • SIGEV_THREAD:定时器到期后,内核会以sigev_notification_attributes为线程属性创建一个线程,线程的入口地址为sigev_notify_function,传入sigev_value作为一个参数。


. struct itimerspec结构的定义如下:

struct itimerspec
{
struct timespec it_interval; // 时间间隔
struct timespec it_value; // 首次到期时间
};

struct timespec
{
time_t tv_sec //Seconds.
long tv_nsec //Nanoseconds.
};

定时器工作时,先将it_value的时间值减到0,发送一个信号,再将it_interval的值赋给it_value,重新开始定时,如此反复。如果it_value值被设置为0,则定时器停止定时;如果it_interval等于0,那么表示该定时器不是一个时间间隔定时器,一旦it_value到期后定时器就回到未启动状态。


lai个例子:

/*************************************************************************
> File Name : posix_timer.c
> Author : Jalyn
> Mail : JalynFang@outlook.com
> Created Time : 2018年11月11日 星期日 18时27分09秒
************************************************************************/
#include<stdio.h>
#include <signal.h>
#include <time.h>

void function_timer()
{
time_t t;
char p[32];
time(
//strftime(p, sizeof(p), "%T", localtime(
strftime(p, sizeof(p), "%Y-%m-%d %H:%M:%S", localtime(

printf("@Jalyn debug -----> date: %s \n", p);
}


int main(int argc,char *
argv[])
{
int ret;
timer_t timer;
struct sigevent evp;
struct timespec spec;
struct itimerspec time_value;

evp.sigev_value.sival_ptr =
/*定时器到期时,会产生一个信号*/
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGUSR1;
signal(SIGUSR1, function_timer);

/*时钟源选CLOCK_MONOTONIC主要是考虑到系统的实时时钟可能会在
程序运行过程中更改,所以存在一定的不确定性,而CLOCK_MONOTONIC
则不会,较为稳定*/
ret = timer_create(CLOCK_MONOTONIC, &evp,
if( ret )
perror("timer_create");

time_value.it_interval.tv_sec = 1; /*每秒触发一次*/
time_value.it_interval.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC,
time_value.it_value.tv_sec = spec.tv_sec + 5; /*5秒后启动*/
time_value.it_value.tv_nsec = spec.tv_nsec + 0;

ret = timer_settime(timer, CLOCK_MONOTONIC, &time_value, NULL);
if( ret )
perror("timer_settime");

while(1)
{
printf("@Jalyn debug -----> main loop \n");
sleep(1);
}

}
举报

相关推荐

0 条评论