定时器是实时应用中非常重要的组件,在Linux系统中实际上也提供了丰富的定时器的支持,在Android UWB的底层实现中也被广泛应用,本文进行简单的介绍。
定时器
定时器的基本管理就是创建、设置定时时间、启动定时器、定时器超时处理、停止定时器以及删除定时器,接下来按照流程顺序进行介绍。
1.创建定时器
关于使用POSIX定时器的创建,使用timer_create函数创建,定时以下提供了简单的示例。
#include
// 定义定时器结构体,将定时器句柄与相关数据进行绑定,以便定时器超时回调处理
typedef struct {
timer_t hTimerHandle;
// 其他定时器相关的成员变量
} TimerData;
// 创建定时器函数
void createTimer() {
TimerData timerData;
struct sigevent se;
// 设置定时器事件
se.sigev_notify = SIGEV_SIGNAL; // 定时器到期时发送信号
se.sigev_signo = SIGALRM; // 使用SIGALRM信号
se.sigev_value.sival_ptr = &(timerData.hTimerHandle); // 传递定时器句柄
// 创建定时器
timer_create(CLOCK_REALTIME, &se, &(timerData.hTimerHandle));
// 其他处理定时器的操作
}
在上述代码中,timer_create函数用于创建一个定时器。它接受三个参数:
clockid_t clockid
:指定定时器时钟类型,这里使用CLOCK_REALTIME
表示使用实时时钟,可以满足一些应用对于实时性的要求。struct sigevent *sevp
:指向sigevent结构体的指针,该结构体定义了定时器到期时的处理方式。timer_t *timerid
:指向timer_t类型的指针,用于接收创建的定时器句柄。在代码中,我们可以看到,首先定义了一个TimerData的结构体,用于存储定时器句柄和其他相关的定时器数据。在最后的示例中,可以看到timer_t句柄是如何应用到实际的案例中的。
然后,创建了一个sigevent结构体se,并设置了定时器事件的处理方式。
最后,通过调用timer_create函数,将定时器句柄存储在timerData.hTimerHandle
中。
在定时器创建时,还支持一些其他的事件类型,如SIGEV_THREAD等,时间到创建一个新的线程来执行特定的函数。
typedef struct sigevent {
int sigev_notify; // 通知方式
int sigev_signo; // 信号编号
union sigval sigev_value; // 传递的值
void (*sigev_notify_function)(union sigval); // 线程处理函数
pthread_attr_t *sigev_notify_attributes; // 线程属性
} sigevent_t;
#include
#include
// 定时器线程处理函数
void timerThreadHandler(union sigval value) {
// 处理定时器到期事件
}
// 创建定时器函数
void createTimer() {
struct sigevent se;
timer_t timerid;
// 设置定时器事件
se.sigev_notify = SIGEV_THREAD; // 使用线程处理方式
se.sigev_notify_function = timerThreadHandler; // 设置线程处理函数
se.sigev_notify_attributes = NULL;
// 创建定时器
timer_create(CLOCK_REALTIME, &se, &timerid);
// 其他处理定时器的操作
}
2.设置定时器的时间,启动定时器
struct itimerspec
是一个用于设置定时器的结构体,在Linux中定义在头文件中。它包含两个成员变量:it_interval和it_value。
struct itimerspec {
struct timespec it_interval; // 定时器的间隔时间
struct timespec it_value; // 定时器的初始值
};
其中,每个成员变量的含义如下:
通过设置it_interval和it_value的值,可以控制定时器的触发时间和触发频率。
以下是使用struct itimerspec结构体来设置定时器的间隔时间和初始值的示例:
#include
void setTimer() {
timer_t timerid;
struct itimerspec its;
// 设置定时器间隔时间为2秒,初始值为3秒
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
its.it_value.tv_sec = 3;
its.it_value.tv_nsec = 0;
// 设置定时器
timer_settime(timerid, 0, &its, NULL);
// 其他处理定时器的操作
}
首先定义了一个itimerspec结构体变量its,并设置了定时器的间隔时间和初始值。
然后,通过调用timer_settime函数来设置定时器。最后,可以进行其他处理定时器的操作。
需要注意的是,it_interval.tv_nsec和it_value.tv_nsec的时间单位是纳秒。在设置定时器时,可以根据需要将其设为不同的值,以实现所需的定时触发行为。
3.停止定时器
停止定时器相对比较简单,将时间相关参数设置为0即可。
static struct itimerspec its = {{0, 0}, {0, 0}};
timer_settime(timerData.hTimerHandle, 0, &its, NULL);
4.删除定时器
要删除定时器,需要等定时器停止运行之后才能删除,所以第一步应停止定时器。
timer_delete(timerData.hTimerHandle);
//对于存放定时器相关数据的结构体可以清空
memset(&timeData, (uint8_t)0x00, sizeof(TimerData));
5. Android UWB HAL应用
在Android UWB HAL实现中,对定时器进行了一定的封装,如下:
/*
**Timer Handle structure containing details of a timer.
*/
typedef struct phOsalUwb_TimerHandle {
timer_t hTimerHandle; /* Handle of the timer */
/* Timer callback function to be invoked */
pphOsalUwb_TimerCallbck_t Application_callback;
void* pContext; /* Parameter to be passed to the callback function */
phOsalUwb_TimerStates_t eState; /* Timer states */
/* Osal Timer message posted on User Thread */
phLibUwb_Message_t tOsalMessage;
//...
} phOsalUwb_TimerHandle_t, *pphOsalUwb_TimerHandle_t;
在timer_t句柄的基础之上增加了相关的回调函数、消息、上下文参数等等,基于定时器实现相关的访问需求。
在phOsalUwb_Timer的实现中,定义了一个phOsalUwb_TimerHandle_t的定时器数组,可以支持多个定时器,以支持多个定时任务的处理。
// 获取自定义定时器句柄
pTimerHandle = (phOsalUwb_TimerHandle_t*)&apTimerInfo[dwIndex];
// 设置定时时间,略
//启动定时器
timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL);
// 停止定时器
static struct itimerspec its = {{0, 0}, {0, 0}};
timer_settime(pTimerHandle->hTimerHandle, 0, &its, NULL);
// 删除定时器
timer_delete(pTimerHandle->hTimerHandle)
// 由于自定义了定时器结构,需要清除存储的相关数据,这里直接全部设置为0.
/* Clear Timer structure used to store timer related data */
memset(pTimerHandle, (uint8_t)0x00, sizeof(phOsalUwb_TimerHandle_t));