ptpd 1588协议关于多个定时器的实现方式解析
来源:互联网 发布:mac邮箱怎么设置签名 编辑:程序博客网 时间:2024/06/05 02:28
1588时间协议,需要实现多个定时器,以对系统各个事件进行定时管理,那它怎么实现多个定时器的,真的挺巧妙的,我们来解析下
PtpClock *
ptpdStartup(int argc, char **argv, Integer16 * ret, RunTimeOpts * rtOpts)
{
...
if(!timerSetup(ptpClock->timers)) { //初始化所有的计时器,保留一个指向所有计时器的指针
PERROR("failed to set up event timers");
*ret = 2;
free(ptpClock);
return 0;
}
...
}
Boolean timerSetup(IntervalTimer *itimers)
{
{
Boolean ret = TRUE;
/* WARNING: these descriptions MUST be in the same order,
* and in the same number as the enum in ptp_timers.h
*/
* and in the same number as the enum in ptp_timers.h
*/
static const char* timerDesc[PTP_MAX_TIMER] = { //这里是我们需要的计时器类型
"PDELAYREQ_INTERVAL",
"DELAYREQ_INTERVAL",
"SYNC_INTERVAL",
"ANNOUNCE_RECEIPT",
"ANNOUNCE_INTERVAL",
"UNICAST_GRANT",
"OPERATOR_MESSAGES",
"LEAP_SECOND_PAUSE",
"STATUSFILE_UPDATE",
"PANIC_MODE",
"PERIODIC_INFO_TIMER",
#ifdef PTPD_STATISTICS
"STATISTICS_UPDATE",
#endif /* PTPD_STATISTICS */
"MASTER_NETREFRESH",
"CALIBRATION_DELAY",
"CLOCK_UPDATE",
"TIMINGDOMAIN_UPDATE"
};
"PDELAYREQ_INTERVAL",
"DELAYREQ_INTERVAL",
"SYNC_INTERVAL",
"ANNOUNCE_RECEIPT",
"ANNOUNCE_INTERVAL",
"UNICAST_GRANT",
"OPERATOR_MESSAGES",
"LEAP_SECOND_PAUSE",
"STATUSFILE_UPDATE",
"PANIC_MODE",
"PERIODIC_INFO_TIMER",
#ifdef PTPD_STATISTICS
"STATISTICS_UPDATE",
#endif /* PTPD_STATISTICS */
"MASTER_NETREFRESH",
"CALIBRATION_DELAY",
"CLOCK_UPDATE",
"TIMINGDOMAIN_UPDATE"
};
int i = 0;
startEventTimers();
for(i=0; i<PTP_MAX_TIMER; i++) { //创建上面所枚举的计时器
itimers[i].data = NULL;
itimers[i].data = (void *)(createEventTimer(timerDesc[i]));
if(itimers[i].data == NULL) {
ret = FALSE;
}
}
itimers[i].data = (void *)(createEventTimer(timerDesc[i]));
if(itimers[i].data == NULL) {
ret = FALSE;
}
}
return ret;
}
void
startEventTimers(void)
{
struct itimerval itimer;
startEventTimers(void)
{
struct itimerval itimer;
DBG("initTimer\n");
#ifdef __sun
sigset(SIGALRM, SIG_IGN);
#else
signal(SIGALRM, SIG_IGN);
#endif /* __sun */
sigset(SIGALRM, SIG_IGN);
#else
signal(SIGALRM, SIG_IGN);
#endif /* __sun */
elapsed = 0;
itimer.it_value.tv_sec = itimer.it_interval.tv_sec = 0;
itimer.it_value.tv_usec = itimer.it_interval.tv_usec =
US_TIMER_INTERVAL;
itimer.it_value.tv_sec = itimer.it_interval.tv_sec = 0;
itimer.it_value.tv_usec = itimer.it_interval.tv_usec =
US_TIMER_INTERVAL;
#ifdef __sun
sigset(SIGALRM, timerSignalHandler);
#else
signal(SIGALRM, timerSignalHandler); //定时响应行数
#endif /* __sun */
setitimer(ITIMER_REAL, &itimer, 0); //使用高精度定时
}
sigset(SIGALRM, timerSignalHandler);
#else
signal(SIGALRM, timerSignalHandler); //定时响应行数
#endif /* __sun */
setitimer(ITIMER_REAL, &itimer, 0); //使用高精度定时
}
static void
timerSignalHandler(int sig)
{
elapsed++; //非常简单,就使用这个全局计数器进行计时,这个是定时器使用的关键
/* be sure to NOT call DBG in asynchronous handlers! */
}
timerSignalHandler(int sig)
{
elapsed++; //非常简单,就使用这个全局计数器进行计时,这个是定时器使用的关键
/* be sure to NOT call DBG in asynchronous handlers! */
}
//接下来我们看看它怎么创建定时器的
EventTimer
*createEventTimer(const char* id)
{
*createEventTimer(const char* id)
{
EventTimer *timer;
if ( !(timer = calloc (1, sizeof(EventTimer))) ) {
return NULL;
}
return NULL;
}
setupEventTimer(timer);
strncpy(timer->id, id, EVENTTIMER_MAX_DESC);
/* maintain the linked list */
if(_first == NULL) {//创建定时器链表
_first = timer;
}
_first = timer;
}
if(_last != NULL) {
timer->_prev = _last;
timer->_prev->_next = timer;
}
timer->_prev = _last;
timer->_prev->_next = timer;
}
_last = timer;
timer->_first = _first;
DBGV("created itimer eventtimer %s\n", timer->id);
return timer;
}
}
void
setupEventTimer(EventTimer *timer)
{
setupEventTimer(EventTimer *timer)
{
if(timer == NULL) {
return;
}
return;
}
memset(timer, 0, sizeof(EventTimer));
timer->start = eventTimerStart_itimer; //启动
timer->stop = eventTimerStop_itimer; //停止
timer->reset = eventTimerReset_itimer; //复位
timer->shutdown = eventTimerShutdown_itimer; //关闭
timer->isExpired = eventTimerIsExpired_itimer; //判断定时器是否溢出,或者说是否到期了
timer->isRunning = eventTimerIsRunning_itimer; //定时器状态
}
timer->stop = eventTimerStop_itimer; //停止
timer->reset = eventTimerReset_itimer; //复位
timer->shutdown = eventTimerShutdown_itimer; //关闭
timer->isExpired = eventTimerIsExpired_itimer; //判断定时器是否溢出,或者说是否到期了
timer->isRunning = eventTimerIsRunning_itimer; //定时器状态
}
//我们关键看下,启动和判断溢出
static void
eventTimerStart_itimer(EventTimer *timer, double interval)
{
eventTimerStart_itimer(EventTimer *timer, double interval)
{
timer->expired = FALSE;
timer->running = TRUE;
timer->running = TRUE;
/*
* US_TIMER_INTERVAL defines the minimum interval between sigalarms.
* timerStart has a float parameter for the interval, which is casted to integer.
* very small amounts are forced to expire ASAP by setting the interval to 1
*/
timer->itimerLeft = (interval * 1E6) / US_TIMER_INTERVAL;
if(timer->itimerLeft == 0){
/*
* the interval is too small, raise it to 1 to make sure it expires ASAP
*/
timer->itimerLeft = 1; //最小的计时单位时1
}
timer->itimerInterval = timer->itimerLeft; //设置响应间隔
* US_TIMER_INTERVAL defines the minimum interval between sigalarms.
* timerStart has a float parameter for the interval, which is casted to integer.
* very small amounts are forced to expire ASAP by setting the interval to 1
*/
timer->itimerLeft = (interval * 1E6) / US_TIMER_INTERVAL;
if(timer->itimerLeft == 0){
/*
* the interval is too small, raise it to 1 to make sure it expires ASAP
*/
timer->itimerLeft = 1; //最小的计时单位时1
}
timer->itimerInterval = timer->itimerLeft; //设置响应间隔
DBG2("timerStart: Set timer %s to %f New interval: %d; new left: %d\n", timer->id, interval, timer->itimerLeft , timer->itimerInterval);
}
}
//溢出判断
static Boolean
eventTimerIsExpired_itimer(EventTimer *timer)
{
eventTimerIsExpired_itimer(EventTimer *timer)
{
Boolean ret;
itimerUpdate(timer);
ret = timer->expired;
DBG2("timerIsExpired: Timer %s %s expired\n", timer->id,
timer->expired ? "is" : "is not");
timer->expired ? "is" : "is not");
if(ret) {
timer->expired = FALSE;
}
timer->expired = FALSE;
}
return ret;
}
static void
itimerUpdate(EventTimer *et)
{
itimerUpdate(EventTimer *et)
{
EventTimer *timer = NULL;
if (elapsed <= 0)
return;
return;
/*
* if time actually passed, then decrease every timer left
* the one(s) that went to zero or negative are:
* a) rearmed at the original time (ignoring the time that may have passed ahead)
* b) have their expiration latched until timerExpired() is called
*/
* if time actually passed, then decrease every timer left
* the one(s) that went to zero or negative are:
* a) rearmed at the original time (ignoring the time that may have passed ahead)
* b) have their expiration latched until timerExpired() is called
*/
/*每次都减去elapsed,elapsed前面已经说了,是个全局计时
*如果时间已经溢出了,他就重新计时,并返回溢出信号
*/
for(timer = et->_first; timer != NULL; timer = timer->_next) {
if ( (timer->itimerInterval > 0) && ((timer->itimerLeft -= elapsed) <= 0)) {
timer->itimerLeft = timer->itimerInterval;
timer->expired = TRUE;
DBG("TimerUpdate: Timer %s has now expired. Re-armed with interval %d\n", timer->id, timer->itimerInterval);
}
}
if ( (timer->itimerInterval > 0) && ((timer->itimerLeft -= elapsed) <= 0)) {
timer->itimerLeft = timer->itimerInterval;
timer->expired = TRUE;
DBG("TimerUpdate: Timer %s has now expired. Re-armed with interval %d\n", timer->id, timer->itimerInterval);
}
}
elapsed = 0; //已经减去了,重置
}
//简单点说,就是使用一个全局定时器计数,再创建一系列定时器,轮询这些定时器是否溢出,已达到多个定时器的目的
阅读全文
0 0
- ptpd 1588协议关于多个定时器的实现方式解析
- 关于java中定时器的实现 三种方式
- FSL 1588 PTPD简要分析!
- LINUX 定时器的实现方式
- 定时器的实现方式分析
- 高效定时器的实现方式
- Android 定时器的实现方式(TimerTask、Handler)及 Handler使用解析
- Android 定时器的实现方式(TimerTask、Handler)及 Handler使用解析
- Spring定时器的两种实现方式
- Spring定时器的两种实现方式
- Spring定时器的两种实现方式
- Linux 下定时器的实现方式分析
- Linux 下定时器的实现方式分析
- Linux 下定时器的实现方式分析
- spring定时器的两种实现方式
- linux 下定时器的实现方式分析
- Spring定时器的两种实现方式
- Spring定时器的两种实现方式
- ant的安装配置
- 挑战程序竞赛系列(18):3.1查找第k大的值
- js 键盘记录
- buddy内存分配算法
- Server Tomcat v8.5 Server at localhost failed to start.
- ptpd 1588协议关于多个定时器的实现方式解析
- Hibernate不能自动建数据表解决办法
- dumpsys命令的用法
- hdu 1045 二分图
- JM8.6之参考图像管理
- html radio的onclick事件设置
- patch_download
- 【stm32f407】CAN总线
- C语言的特点