linux C 标准定时器使用示例

本文介绍了C linux系统自带的定时器接口使用方法,并封装了接口方便调用,文末有提供示例代码;
示例代码演示为创建两个定时器,使用同一个回调函数,在回调函数中用创建传入的时间ID区分不同的定时器事件。
定时器A为循环触发2s触发一次,定时器B为循环触发 4s触发一次。
注:编译示例代码时需要链接-lrt -lpthread这两个库,lrt为定时器需要,-lpthread为示例sem信号量相关接口需要

需要包含的头文件

#include <signal.h>
#include <time.h>

结构体和枚举

/* 定时器类型枚举 */
typedef enum
{
    /* 循环触发定时器 */
    MY_CYCLE_TIMER = 0,

    /* 只触发一次定时器 */
    MY_ONCE_TIMER = 1,
} MyTimerType_E;

/* 定时器事件类型枚举 */
typedef enum
{
    /* A事件 */
    MY_TIMER_A_EVENT = 0,

    /* B事件 */
    MY_TIMER_B_EVENT = 1,
} MyTimerEventType_E;

#if 0
/* 系统自带结构体,在此当注释方便开发理解 */
union sigval
{

/* integer value */
int sival_int;
/* pointer value */
void *sival_ptr;

}
#endif

typedef void (*timerCallBcak)(union sigval v);

接口实现

创建定时器接口

/*!
* @brief 创建定时器
* @details 创建定时器
* @param[In] cb 定时器回调函数
* @param[In] event 定时器事件ID
* @return 返回值说明
* @retval 返回创建的定时器ID  创建失败返回-1
*/
timer_t MyCreateTimer(timerCallBcak cb, MyTimerEventType_E event)
{
    int ret = 0;
    struct sigevent sTimer;
    timer_t timerId;

    memset(&sTimer, 0, sizeof(struct sigevent));

    /* 这个值作为定时器回调参数传入,也可以传入指针,此处用来区分定时器事件 */
    sTimer.sigev_value.sival_int = event;

    sTimer.sigev_notify = SIGEV_THREAD;
    sTimer.sigev_notify_function = cb;

    ret = timer_create(CLOCK_REALTIME, &sTimer, &timerId);
    if (-1 == ret)
    {
        printf("fail to timer_create!\n");
        return NULL;
    }

    return timerId;
}

启动定时器接口

/*!
* @brief 启动定时器
* @details 启动定时器
* @param[In] timerId 定时器ID
* @param[In] timeout 超时时间 单位为秒
* @param[In] timerType 定时器类型
* @return 返回值说明
* @retval 0启动成功 -1启动失败
*/
int MyStartTimer(timer_t timerId, int timeout, MyTimerType_E timerType)
{
    struct itimerspec timerInterval;
    int ret = 0;

    memset(&timerInterval, 0x0, sizeof(struct itimerspec));
    timerInterval.it_value.tv_sec = timeout;
    timerInterval.it_value.tv_nsec = 0;
    if (MY_CYCLE_TIMER == timerType)
    {
        timerInterval.it_interval = timerInterval.it_value;
    }

    ret = timer_settime(timerId, 0, &timerInterval, NULL);
    if (-1 == ret)
    {
        printf("fail to Liot_startTimer\n");
        return ret;
    }
    return 0;
}

停止定时器接口

/*!
* @brief 停止定时器
* @details 停止定时器
* @param[In] timerId 定时器ID
* @return 返回值说明
* @retval 0停止成功 -1停止失败
*/
int MyStopTimer(timer_t timerId)
{
    struct itimerspec timerInterval;
    int ret = 0;

    memset(&timerInterval, 0x0, sizeof(struct itimerspec));

    ret = timer_settime(timerId, 0, &timerInterval, NULL);
    if (-1 == ret)
    {
        printf("fail to Liot_stopTimer\n");
        return ret;
    }
    return 0;
}

销毁定时器接口

/*!
* @brief 销毁定时器
* @details 销毁定时器
* @param[In] timerId 定时器ID
* @return 返回值说明
* @retval void
*/
void MyDeleteTimer(timer_t timerId)
{
    timer_delete(timerId);
}

示例代码

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <semaphore.h>
#include <string.h>

/* 定时器类型枚举 */
typedef enum
{
    /* 循环触发定时器 */
    MY_CYCLE_TIMER = 0,

    /* 只触发一次定时器 */
    MY_ONCE_TIMER = 1,
} MyTimerType_E;

/* 定时器事件类型枚举 */
typedef enum
{
    /* A事件 */
    MY_TIMER_A_EVENT = 0,

    /* B事件 */
    MY_TIMER_B_EVENT = 1,
} MyTimerEventType_E;

#if 0
/* 系统自带结构体,在此当注释方便开发理解 */
union sigval
{

/* integer value */
int sival_int;
/* pointer value */
void *sival_ptr;

}
#endif

typedef void (*timerCallBcak)(union sigval v);

/* 定时器A的ID */
static timer_t g_s_myTimerIdA;

/* 定时器B的ID */
static timer_t g_s_myTimerIdB;

static sem_t g_s_mySem;
/*!
* @brief 创建定时器
* @details 创建定时器
* @param[In] cb 定时器回调函数
* @param[In] event 定时器事件ID
* @return 返回值说明
* @retval 返回创建的定时器ID  创建失败返回-1
*/
timer_t MyCreateTimer(timerCallBcak cb, MyTimerEventType_E event)
{
    int ret = 0;
    struct sigevent sTimer;
    timer_t timerId;

    memset(&sTimer, 0, sizeof(struct sigevent));

    /* 这个值作为定时器回调参数传入,也可以传入指针,此处用来区分定时器事件 */
    sTimer.sigev_value.sival_int = event;

    sTimer.sigev_notify = SIGEV_THREAD;
    sTimer.sigev_notify_function = cb;

    ret = timer_create(CLOCK_REALTIME, &sTimer, &timerId);
    if (-1 == ret)
    {
        printf("fail to timer_create!\n");
        return NULL;
    }

    return timerId;
}

/*!
* @brief 启动定时器
* @details 启动定时器
* @param[In] timerId 定时器ID
* @param[In] timeout 超时时间 单位为秒
* @param[In] timerType 定时器类型
* @return 返回值说明
* @retval 0启动成功 -1启动失败
*/
int MyStartTimer(timer_t timerId, int timeout, MyTimerType_E timerType)
{
    struct itimerspec timerInterval;
    int ret = 0;

    memset(&timerInterval, 0x0, sizeof(struct itimerspec));
    timerInterval.it_value.tv_sec = timeout;
    timerInterval.it_value.tv_nsec = 0;
    if (MY_CYCLE_TIMER == timerType)
    {
        timerInterval.it_interval = timerInterval.it_value;
    }

    ret = timer_settime(timerId, 0, &timerInterval, NULL);
    if (-1 == ret)
    {
        printf("fail to Liot_startTimer\n");
        return ret;
    }
    return 0;
}

/*!
* @brief 停止定时器
* @details 停止定时器
* @param[In] timerId 定时器ID
* @return 返回值说明
* @retval 0停止成功 -1停止失败
*/
int MyStopTimer(timer_t timerId)
{
    struct itimerspec timerInterval;
    int ret = 0;

    memset(&timerInterval, 0x0, sizeof(struct itimerspec));

    ret = timer_settime(timerId, 0, &timerInterval, NULL);
    if (-1 == ret)
    {
        printf("fail to Liot_stopTimer\n");
        return ret;
    }
    return 0;
}

/*!
* @brief 销毁定时器
* @details 销毁定时器
* @param[In] timerId 定时器ID
* @return 返回值说明
* @retval void
*/
void MyDeleteTimer(timer_t timerId)
{
    timer_delete(timerId);
}

void MyTimerCallback(union sigval v)
{
    static int i = 0;
    time_t t = time(NULL);
    struct tm *dateTime = localtime(&t);
    char *date = asctime(dateTime);
    
    if (MY_TIMER_A_EVENT == v.sival_int)
    {
        printf("AAAAAtimer is coming! date:%s\n", date);
    }
    else if (MY_TIMER_B_EVENT == v.sival_int)
    {
        printf("BBBBBtimer is coming! date:%s\n", date);
    }

    i++;
    if (i >= 6)
    {
        MyStopTimer(g_s_myTimerIdA);
        MyStopTimer(g_s_myTimerIdB);
        sem_post(&g_s_mySem);
    }
}

int main()
{
    sem_init(&g_s_mySem, 0, 0);

    g_s_myTimerIdA = MyCreateTimer(MyTimerCallback, MY_TIMER_A_EVENT);
    g_s_myTimerIdB = MyCreateTimer(MyTimerCallback, MY_TIMER_B_EVENT);

    MyStartTimer(g_s_myTimerIdA, 2, MY_CYCLE_TIMER);
    MyStartTimer(g_s_myTimerIdB, 4, MY_CYCLE_TIMER);

    printf("wait timer stop\n");
    sem_wait(&g_s_mySem);
    printf("timer stop\n");
    MyDeleteTimer(g_s_myTimerIdA);
    MyDeleteTimer(g_s_myTimerIdB);
    g_s_myTimerIdA = NULL;
    g_s_myTimerIdB = NULL;
    return 0;
}

运行结果

./a.out 
wait timer stop
AAAAAtimer is coming! date:Thu Sep 29 08:22:00 2022

AAAAAtimer is coming! date:Thu Sep 29 08:22:02 2022

BBBBBtimer is coming! date:Thu Sep 29 08:22:02 2022

AAAAAtimer is coming! date:Thu Sep 29 08:22:04 2022

AAAAAtimer is coming! date:Thu Sep 29 08:22:06 2022

BBBBBtimer is coming! date:Thu Sep 29 08:22:06 2022

timer stop
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux 中,可以使用 POSIX 定时器来实现定时任务。下面是一个使用 POSIX 定时器实现定时任务的 C 语言示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <time.h> static void handler(int sig, siginfo_t *si, void *uc) { printf("定时器已经超时 %d 次\n", si->si_value.sival_int); } int main(int argc, char *argv[]) { timer_t timerid; struct sigevent sev; struct itimerspec its; long long freq_nanosecs; sigset_t mask; int sig; if (argc != 3) { fprintf(stderr, "用法: %s <超时时间(秒)> <超时次数>\n", argv[0]); exit(EXIT_FAILURE); } sig = SIGRTMIN; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = sig; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) { perror("timer_create"); exit(EXIT_FAILURE); } freq_nanosecs = atoll(argv[1]) * 1000000000; its.it_value.tv_sec = freq_nanosecs / 1000000000; its.it_value.tv_nsec = freq_nanosecs % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; if (timer_settime(timerid, 0, &its, NULL) == -1) { perror("timer_settime"); exit(EXIT_FAILURE); } printf("定时器已经开始,每 %lld 秒超时一次,共超时 %s 次\n", (long long) its.it_value.tv_sec, argv[2]); sigemptyset(&mask); sigaddset(&mask, sig); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { perror("sigprocmask"); exit(EXIT_FAILURE); } struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); if (sigaction(sig, &sa, NULL) == -1) { perror("sigaction"); exit(EXIT_FAILURE); } int count = 0; while (count < atoi(argv[2])) { pause(); count++; } exit(EXIT_SUCCESS); } ``` 这个示例代码中,我们使用了 POSIX 定时器来实现定时任务。首先,我们使用 timer_create 函数创建了一个定时器对象,并使用 timer_settime 函数指定了定时器的超时时间和超时次数。然后,使用 sigaction 函数安装了一个信号处理程序,该程序会在定时器超时时被调用。最后,我们使用 pause 函数使程序处于等待状态,直到定时器超时指定的次数后程序退出。 希望这个示例代码能够帮助你更好地理解如何在 Linux使用 C 语言实现定时任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

axk0909

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值