POSIX Timer
SYNOPSIS
#include <signal.h> /* only timer_create need this header */
#include <time.h> int timer_create(clockid_t clockid, struct sigevent *restrict evp, timer_t *restrict timerid);
int timer_delete(timer_t timerid); int timer_gettime(timer_t timerid, struct itimerspec *value);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *restrict new_value, struct itimerspec *restrict old_value); int timer_getoverrun(timer_t timerid);
Date Structure
struct sigevent 的详细定义请参见:http://www.cnblogs.com/LubinLew/p/POSIX-DataStructure.html#sigevent
struct itimerspec 的详细定义请参见:http://www.cnblogs.com/LubinLew/p/POSIX-DataStructure.html#itimerspec
clockid_t 的详细定义请参见:http://www.cnblogs.com/LubinLew/p/POSIX-DataStructure.html#clockid_t
FUNCTION DETAIL
1) timer_create
DESCRIPTION
函数 timer_create 会创建一个timer(每进程), 返回的timer id 在调用进程中是唯一的, 创建后的timer处于停止(disarmed)状态.
PARAMETERS
① clockid [IN]
使用的时钟类型, 取值范围为以下4种
② evp [IN]
timer到期时的通知方法,详见:http://www.cnblogs.com/LubinLew/p/POSIX-DataStructure.html#sigevent
该类型结构体使用之前一定要初始化(memset等), 否则可能会出现timer到期无动作的异常情况.
③ timerid [OUT]
创建的timer的id 通过这个指针返回.
RETURN VALUE
timer创建成功该函数返回0,并且更新timerid;否则函数返回-1,并且设置errno标识错误种类,具体如下.
[EAGAIN]
系统没有足够的信号队列资源来响应创建一个新timer的请求,或者调用进程创建的timer总数已达到最大值,无法创建新的timer.
[EINVAL]
第一个参数无效(The specified clock ID is not defined.)
[ENOTSUP]
该平台实现不支持clock ID 为CLOCK_PROCESS_CPUTIME_ID 和 CLOCK_THREAD_CPUTIME_ID.
2) timer_delete
DESCRIPTION
通过timder id删除指定的 timer.
如果调用这个函数时,timer处于激活(armed)状态, 删除前会先将这个timer状态变更为未激活(disarmed)状态.
挂起等待timer(删除的)产生信号的行为是未定义的.
PARAMETERS
① timerid [IN]
指定的timer
RETURN VALUE
timer删除成功该函数返回0;否则函数返回-1,并且设置errno标识错误种类,具体如下.
[EINVAL]
参数无效(The timer ID specified by timerid is not a valid timer ID.)
3) timer_settime
DESCRIPTION
启动(armed) / 停止(disarmed) / 重置 timer.
PARAMETERS
① timerid [IN]
指定的timer
② flags [IN]
flags 取值只有2个 : 0 和 TIMER_ABSTIME.
⑴ 当 flags 为 0 时, new_value->it_value 表示希望timer首次到期时的时间与启动timer的时间间隔(例如,希望timer 在 2秒后到期).
⑵ 当flags为 TIMER_ABSTIME 时, new_value->it_value 表示希望timer首次到期的绝对时间(例如希望timer 在 01:23:45 到期);
如果new_value->it_value 设定的绝对时间 早于 当前的绝对时间, 那么timer会立即到期.
如果时钟 CLOCK_REALTIME 被调整了,那么timer的首次过期时间也会适当调整.
③ new_value [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 [OUT]
取得上一次的设置的new_value.
RETURN VALUE
操作成功该函数返回0;否则函数返回-1,并且设置errno标识错误种类,具体如下:
[EINVAL]
⑴ [shall fail] new_value.it_value is negative; or new_value->it_value.tv_nsec is negative or greater than 999,999,999.
⑵ [may fail] new_value->it_interval不为0,并且timer的到期通知方式为创建新线程(sigev_sigev_notify = SIGEV_THREAD)并且在线程属性中设置了固定的栈地址.
4) timer_gettime
DESCRIPTION
获取指定timer的信息(离timer到期的剩余时间 和 timer的循环时间间隔).
PARAMETERS
① timerid [IN]
指定的timer
② value[OUT]
value->it_value : 离timer到期的剩余时间
value->it_interval : timer的循环时间间隔
RETURN VALUE
操作成功该函数返回0;否则函数返回-1,并且设置errno标识错误种类,具体如下:
[EINVAL]
timerid is invalid.
5) timer_getoverrun
DESCRIPTION
当一个timer到期并且上一次到期时产生的信号还处于挂起状态时,不会产生新的信号(即丢弃一个信号),这就是定时器超限(overrun), 丢弃的信号数量就是 overrun count。
对于一个给定的timer, 在任何时间点只能有一个信号在进程中排队, 这是POSIX.1-2001中指定的, 因为不这样做,排队信号的数量很容易达到系统的上限.
因为系统调度延迟或者信号被暂时阻塞都会造成信号产生到信号被发送( (e.g., caught by a signal handler))或者接收((e.g., using sigwaitinfo(2)))之间有一个延迟的时间段,在这个时间段中可能会有多次的timer到期.
程序可以通过调用timer_getoverrun来确定一个指定的定时器出现这种超限的次数, 从而精确能精确的计算出在给定时间内timer到期了多少次。
定时器超限只能发生在同一个定时器产生的信号上。多个定时器,甚至是那些使用相同的时钟和信号的定时器,所产生的信号都会排队而不会丢失。
如果超限运行的次数等于或大于 {DELAYTIMER_MAX},则此调用会返回 {DELAYTIMER_MAX}.
PARAMETERS
① timerid [IN]
指定的timer
RETURN VALUE
执行成功,返回 "overrun count" (>=0), 失败返回-1,并且设置errno标识错误种类,具体如下:
[EINVAL]
timerid is invalid.
EXAMPLE
例子1:一次性timer,使用相对时间
#include <signal.h> /* union sigval / struct sigevent */
#include <stdio.h> /* printf */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */
#include <time.h> #define printf_with_time(format, ...) \
{ \
struct timespec spec; \
clock_gettime(CLOCK_MONOTONIC, &spec); \
printf("[%lu:%lu]"format"\n", spec.tv_sec, spec.tv_nsec, ##__VA_ARGS__);\
} timer_t id; void timer_notify_cb(union sigval val)
{
printf_with_time("timer expiration");
printf_with_time("delete timer");
timer_delete(id);
} int main(void)
{
/* Variable Definition */
struct timespec spec;
struct sigevent ent;
struct itimerspec value;
struct itimerspec get_val; /* Init */
memset(&ent, 0x00, sizeof(struct sigevent));
memset(&get_val, 0x00, sizeof(struct itimerspec)); /* create a timer */
ent.sigev_notify = SIGEV_THREAD;
ent.sigev_notify_function = timer_notify_cb;
printf_with_time("create timer");
timer_create(CLOCK_MONOTONIC, &ent, &id); /* start a timer */
value.it_value.tv_sec = ;
value.it_value.tv_nsec = ;
value.it_interval.tv_sec = ;
value.it_interval.tv_nsec = ;
printf_with_time("start timer");
timer_settime(id, , &value, NULL); sleep();
return ;
}
一次性timer(相对时间)
例子2:循环timer,使用绝对时间
#include <signal.h> /* union sigval / struct sigevent */
#include <stdio.h> /* printf */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */
#include <time.h> #define printf_with_time(format, ...) \
{ \
struct timespec spec; \
clock_gettime(CLOCK_MONOTONIC, &spec); \
printf("[%lu:%lu]"format"\n", spec.tv_sec, spec.tv_nsec, ##__VA_ARGS__);\
} void timer_notify_cb(union sigval val)
{
printf_with_time("timer expiration"); } int main(void)
{
/* Variable Definition */
timer_t id;
struct timespec spec;
struct sigevent ent;
struct itimerspec value;
struct itimerspec get_val; /* Init */
memset(&ent, 0x00, sizeof(struct sigevent));
memset(&get_val, 0x00, sizeof(struct itimerspec)); /* create a timer */
ent.sigev_notify = SIGEV_THREAD;
ent.sigev_notify_function = timer_notify_cb;
printf_with_time("create timer");
timer_create(CLOCK_REALTIME, &ent, &id); /* CLOCK_REALTIME */ /* start a timer */
clock_gettime(CLOCK_REALTIME, &spec); /* CLOCK_REALTIME */
value.it_value.tv_sec = spec.tv_sec + ;
value.it_value.tv_nsec = spec.tv_nsec + ;
value.it_interval.tv_sec = ; /* per second */
value.it_interval.tv_nsec = ;
printf_with_time("start timer");
timer_settime(id, TIMER_ABSTIME, &value, NULL); /* TIMER_ABSTIME */ sleep();
printf_with_time("delete timer");
timer_delete(id);
return ;
}
循环timer(绝对时间)
例子3:timer_gettime
#include <signal.h> /* union sigval / struct sigevent */
#include <stdio.h> /* printf */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */
#include <time.h> #define printf_with_time(format, ...) \
{ \
struct timespec spec; \
clock_gettime(CLOCK_MONOTONIC, &spec); \
printf("[%lu:%lu]"format"\n", spec.tv_sec, spec.tv_nsec, ##__VA_ARGS__);\
} timer_t id; void timer_notify_cb(union sigval val)
{
printf_with_time("timer expiration");
} int main(void)
{
/* Variable Definition */
struct timespec spec;
struct sigevent ent;
struct itimerspec value;
struct itimerspec get_val; /* Init */
memset(&ent, 0x00, sizeof(struct sigevent));
memset(&get_val, 0x00, sizeof(struct itimerspec)); /* create a timer */
ent.sigev_notify = SIGEV_THREAD;
ent.sigev_notify_function = timer_notify_cb;
printf_with_time("create timer");
timer_create(CLOCK_MONOTONIC, &ent, &id); /* start a timer */
value.it_value.tv_sec = ;
value.it_value.tv_nsec = ;
value.it_interval.tv_sec = ;
value.it_interval.tv_nsec = ;
printf_with_time("start timer");
timer_settime(id, , &value, NULL); sleep();
timer_gettime(id, &get_val);
printf_with_time("timer will expiration after %lu.%lus", get_val.it_value.tv_sec, get_val.it_value.tv_nsec);
printf_with_time("timer repeat period = %lu.%lus", get_val.it_interval.tv_sec, get_val.it_interval.tv_nsec); sleep();
printf_with_time("delete timer");
timer_delete(id); return ;
}
timer_gettime
例子4:timer_getoverrun
#include <signal.h> /* union sigval / struct sigevent */
#include <stdio.h> /* printf */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */
#include <time.h> #define printf_with_time(format, ...) \
{ \
struct timespec spec; \
clock_gettime(CLOCK_MONOTONIC, &spec); \
printf("[%lu:%lu]"format"\n", spec.tv_sec, spec.tv_nsec, ##__VA_ARGS__);\
} timer_t id; void timer_notify_cb(union sigval val)
{
printf_with_time("timer expiration");
} int main(void)
{
/* Variable Definition */
struct timespec spec;
struct sigevent ent;
struct itimerspec value;
struct itimerspec get_val; /* Init */
memset(&ent, 0x00, sizeof(struct sigevent));
memset(&get_val, 0x00, sizeof(struct itimerspec)); /* create a timer */
ent.sigev_notify = SIGEV_THREAD;
ent.sigev_notify_function = timer_notify_cb;
printf_with_time("create timer");
timer_create(CLOCK_MONOTONIC, &ent, &id); /* start a timer */
value.it_value.tv_sec = ;
value.it_value.tv_nsec = ;
value.it_interval.tv_sec = ;
value.it_interval.tv_nsec = ;
printf_with_time("start timer");
timer_settime(id, , &value, NULL); sleep();
printf_with_time("overrun count = %d", timer_getoverrun(id));
printf_with_time("delete timer");
timer_delete(id); return ;
}
timer_getoverrun
例子5:发送信号方式通知
#include <signal.h> /* union sigval / struct sigevent */
#include <stdio.h> /* printf */
#include <string.h> /* memset */
#include <unistd.h> /* sleep */
#include <stdlib.h> /* exit */
#include <time.h> #define printf_with_time(format, ...) \
{ \
struct timespec spec; \
clock_gettime(CLOCK_MONOTONIC, &spec); \
printf("[%lu:%lu]"format"\n", spec.tv_sec, spec.tv_nsec, ##__VA_ARGS__);\
} timer_t id; void sighandler_cb(int val)
{
if (SIGUSR2 == val)
{
printf_with_time("sighandler");
}
else
{
printf_with_time("delete timer");
timer_delete(id);
exit(EXIT_SUCCESS);
}
} int main(void)
{
/* Variable Definition */
struct sigevent ent;
struct itimerspec value; /* Init */
memset(&ent, 0x00, sizeof(struct sigevent)); /* register singnal handler */
signal(SIGUSR2, sighandler_cb); /* for timer */
signal(SIGINT, sighandler_cb); /* Ctrl + C */ /* create a timer */
ent.sigev_notify = SIGEV_SIGNAL;
ent.sigev_signo = SIGUSR2;
printf_with_time("create timer");
timer_create(CLOCK_MONOTONIC, &ent, &id); /* start a timer */
value.it_value.tv_sec = ;
value.it_value.tv_nsec = ;
value.it_interval.tv_sec = ;
value.it_interval.tv_nsec = ;
printf_with_time("start timer");
timer_settime(id, , &value, NULL); while();
/* Ctrl + C */ return ;
}
发送信号方式通知
POSIX Timer的更多相关文章
- Linux时间子系统之(六):POSIX timer
专题文档汇总目录 Notes:首先讲解了POSIX timer的标识(唯一识别).POSIX Timer的组织(管理POSIX Timer).内核中如何抽象POSIX Timer:然后分析了POSIX ...
- Linux时间子系统(六) POSIX timer
一.前言 在用户空间接口函数文档中,我们描述了和POSIX timer相关的操作,主要包括创建一个timer.设定timer.获取timer的状态.获取timer overrun的信息.删除timer ...
- 【转】Linux Posix Timer使用
原文网址:http://blog.csdn.net/hongszh/article/details/8608781 最强大的定时器接口来自POSIX时钟系列,其创建.初始化以及删除一个定时器的行动被分 ...
- Linux时间子系统之(五):POSIX Clock
专题文档汇总目录 Notes: 本章主要介绍了若干种类的静态时钟,这些时钟都可以通过k_clock表示,注册到posix_clocks中.这些都是静态时钟,可以分为三大类:各种REALTIME时钟.带 ...
- Linux时间子系统之二:Alarm Timer
一.前言 严格来讲Alarm Timer也算POSIX Timer一部分,包含两种类型CLOCK_REALTIME_ALARM和CLOCK_BOOTTIME_ALARM.分别是在CLOCK_REALT ...
- Linux时间子系统之四:Timer在用户和内核空间流程
用户空间应用中创建一个Timer(alarm/setitimer/POSIX Timer等等),然后程序继续执行: 内核进入创建/设置Timer系统调用,开始计时,在超时后通过何种方式通知用户空间: ...
- Linux时间子系统(五) POSIX Clock
一.前言 clock是timer的基础,任何一个timer都需要运作在一个指定的clock上来.内核中维护了若干的clock,本文第二章描述了clock的基本概念和一些静态定义的posix clock ...
- linux 定时器编程实例(完善中).....
最近在写linux 下的定时器编程实验,测试发现 usleep函数在 x86 架构下的定时还是比较准确的,在arm9下 就不太准了. 今天用linux 下的setitimer()函数进行了定时 器的测 ...
- Linux时间子系统专题汇总
关于Linux时间子系统有两个系列文章讲的非常好,分别是WowoTech和DroidPhone. 还有两本书分别是介绍: Linux用户空间时间子系统<Linux/UNIX系统编程手册>的 ...
随机推荐
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
- C# Linq to Entity 多条件 OR查询
技术背景:框架MVC,linq to Entity 需要一定的lambda书写能力 问题:在简单的orm中完成一些简单的增删查改是通过where insert delete update 完成的,但是 ...
- python 私有方法
最近了解到python私有方法的来由: Python中默认的成员函数,成员变量都是公开的(public),而且python中没有类似public,private等关键词来修饰成员函数,成员变量. 在p ...
- 2018-2019 20165232 Exp5 MSF基础应用
2018-2019 20165232 Exp5 MSF基础应用 一.原理与实践说明 1.实践内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 一个 ...
- TensorFlow windows 安装(base anaconda)
Python conda安装之后(19年默认是python3.7) 1.降级到python3.6 2.查看python版本 3.安装tensorflow
- jQuery使用(十五):when()方法的使用
这个方法再次基于callbacks和deferred对象来实现的一个延迟异步回调来实现的,再when方法内可以添加多个deferred对象作为参数,只有当所有deferred全部被触发了成功的回调函数 ...
- vue md5
安装 cnpm install js-md5 --save 使用 import md5 from 'js-md5' md5('要加密的内容')
- python学习08
python中的异常处理 1.格式 try 语句块 except else finally else 是如果try语句没有异常,就执行,否则不执行 finally 不管程序是否异常,都会执行. 2.异 ...
- XGBboost 特征评分的计算原理
xgboost是基于GBDT原理进行改进的算法,效率高,并且可以进行并行化运算,而且可以在训练的过程中给出各个特征的评分,从而表明每个特征对模型训练的重要性, 调用的源码就不准备详述,本文主要侧重的是 ...
- Java中ArrayList类的用法
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...