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"\n", 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"\n", 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"\n", 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"\n", 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"\n", 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;
}
發送信號方式通知

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM