Linux编程——定时器

2023年 9月 25日 50.6k 0

定时器是实时应用中非常重要的组件,在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:表示定时器的间隔时间,即定时器周期性触发的时间间隔。它是一个struct timespec结构体类型的变量,包含了秒(tv_sec)和纳秒(tv_nsec)两个字段。如果希望定时器只触发一次,可以将it_interval设置为0。
  • it_value:表示定时器的初始值,即定时器首次触发的时间。同样,它也是一个struct timespec结构体类型的变量。
  • 通过设置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));
    
    

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论