zoukankan      html  css  js  c++  java
  • 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种

    CLOCK_REALTIME

    CLOCK_MONOTONIC

    CLOCK_PROCESS_CPUTIME_ID

    CLOCK_THREAD_CPUTIME_ID

    ② 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"
    ", 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 = 2;
        value.it_value.tv_nsec = 0;
        value.it_interval.tv_sec = 0;
        value.it_interval.tv_nsec = 0;
        printf_with_time("start timer");
        timer_settime(id, 0, &value, NULL);
    
        sleep(3);
        return 0;
    }
    一次性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"
    ", 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 + 2;
        value.it_value.tv_nsec = spec.tv_nsec + 0;
        value.it_interval.tv_sec = 1;    /* per second */
        value.it_interval.tv_nsec = 0;
        printf_with_time("start timer");
        timer_settime(id, TIMER_ABSTIME, &value, NULL); /* TIMER_ABSTIME */
    
        sleep(10);
        printf_with_time("delete timer");
        timer_delete(id);
        return 0;
    }
    循环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"
    ", 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 = 5;
        value.it_value.tv_nsec = 0;
        value.it_interval.tv_sec = 2;
        value.it_interval.tv_nsec = 123456789;
        printf_with_time("start timer");
        timer_settime(id, 0, &value, NULL);
    
        sleep(2);
        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(10);
        printf_with_time("delete timer");
        timer_delete(id);
    
        return 0;
    }
    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"
    ", 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 = 1;
        value.it_value.tv_nsec = 0;
        value.it_interval.tv_sec = 0;
        value.it_interval.tv_nsec = 5000;
        printf_with_time("start timer");
        timer_settime(id, 0, &value, NULL);
    
    
        sleep(2);
        printf_with_time("overrun count = %d", timer_getoverrun(id));
        printf_with_time("delete timer");
        timer_delete(id);
    
        return 0;
    }
    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"
    ", 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 = 2;
        value.it_value.tv_nsec = 0;
        value.it_interval.tv_sec = 1;
        value.it_interval.tv_nsec = 0;
        printf_with_time("start timer");
        timer_settime(id, 0, &value, NULL);
    
    
        while(1);
        /* Ctrl + C */
    
        return 0;
    }
    发送信号方式通知

     

  • 相关阅读:
    vue : 无法加载文件 C:Users1AppDataRoaming pmvue.ps1,因为在此系统上禁止运行脚本
    Flutter 常用的第三方库
    Dart 中的类
    Flutter 学习
    在 VSCode 中开发Flutter项目
    Flutter 环境配置的一些坑
    前端资源和优秀项目地址
    一小时学习JQuery材料
    基于RCT6的YX6100语音模块方案
    Java中反射和内省代码实例
  • 原文地址:https://www.cnblogs.com/LubinLew/p/POSIX-Timer.html
Copyright © 2011-2022 走看看