#include <signal.h> #include <time.h> int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid); int timer_delete(timer timer_id); int timer_getoverrun(timer_t timerid); int timer_gettime(timer_t timerid, struct itimerspec *value); int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); typedef struct sigevent { int sigev_notify; int sigev_signo; sigval_t sigev_value; union { int _pad[SIGEV_PAD_SIZE]; int _tid; struct { void (*_function)(sigval_t); pthread_attr_t *_attribute; } _sigev_thread; } _sigev_un; } sigevent_t; struct timespec { time_t tv_sec; long tv_nsec; }; struct itimerspec { struct timespec it_interval; struct timespec it_value; }; sigev_notify 設定為如下值來定制計時器到期後的行為
  1. SIGEV_NONE
    什麼都不做,只提供通過 timer_gettime 和 timer_getoverrun 查詢超時資訊。

  2. SIGEV_SIGNAL
    發送由 sigev_signo 指定的信號到調用進程,sigev_value 的值將被作為 siginfo_t 結構體中 si_value 的值。

  3. SIGEV_THREAD
    以 _sigev_un._attributes 為線程屬性創建一個線程,在新建的線程內部以 sigev_value 為參數調用 _sigev_un._function。

  4. SIGEV_THREAD_ID
    和 SIGEV_SIGNAL 類似,不過它只將信號發送到線程號為 _sigev_un._tid 的線程,注意這裏的線程號不一定是 POSIX 線程號,而是線程調用 gettid 返回的實際線程號,並且這個線程必須實際存在且屬於當前的調用進程。
clockid 設定為如下值來定制計時器時間算法
  1. CLOCK_REALTIME
    系統時間

  2. CLOCK_MONOTONIC
    系統從開機到目前的時間

  3. CLOCK_PROCESS_CPUTIME_ID
    高精度行程時間

  4. CLOCK_THREAD_CPUTIME_ID
    執行緒時間

  5. CLOCK_REALTIME_HR
    高精度系統時間

  6. CLOCK_MONOTONIC_HR
    高精度系統開機時間

timer_settime 設計上的一些要點
  1. 這些函數在 kernel 2.6 後才有提供,kernel 2.4 沒有。
  2. 在編譯時需手動加入 -lrt 的參數,也就是要下 gcc -lrt alarm.c 才可以。
  3. timer_create 的 evp=NULL,代表使用預設值,即送出 SIGALRM 信號。
  4. timer_create 設定成功會傳回 0,並把計時器編號傳入 timerid 供後續函數使用。
  5. timer_settime 的 flags=TIMER_ABSTIME,表示 it_value 使用絕對時間,也就是從 1970 開始的秒數。
  6. timer_settime 的 flags=0,表示 it_value 使用相對時間,也就是目前開始的秒數。
  7. linux 不支援 CLOCK_REALTIME_HR 及 CLOCK_MONOTONIC_HR。
  8. uClibc 0.9.26 不支援此類函數。
下面演示 timer_settime 的使用範例,每二秒顯示系統時間一次。 #include <stdio.h> #include <signal.h> #include <time.h> #include <sched.h> int main(int argc, char *argv[]) { timer_t timer; struct itimerspec timeout; sigset_t block; struct sched_param param; sigemptyset(&block); sigaddset(&block, SIGALRM); sigprocmask(SIG_BLOCK, &block, NULL); timer_create(CLOCK_MONOTONIC, NULL, &timer); timeout.it_interval.tv_sec = 2; timeout.it_interval.tv_nsec = 0; timeout.it_value = timeout.it_interval; timer_settime(timer, 0, &timeout, NULL); while (1) { fprintf(stderr, "%d\n", time(NULL)); sigwaitinfo(&block, NULL); } return 0; }

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()