日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POSIX定时器

發布時間:2023/12/10 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POSIX定时器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最強大的定時器接口來自POSIX時鐘系列,其創建、初始化以及刪除一個定時器的行動被分為三個不同的函數:timer_create()(創建定時器)、timer_settime()(初始化定時器)以及timer_delete(銷毀它)。

?

創建一個定時器:

int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)

??? 進程可以通過調用timer_create()創建特定的定時器,定時器是每個進程自己的,不是在fork時繼承的。clock_id說明定時器是基于哪個時鐘的,*timerid裝載的是被創建的定時器的ID。該函數創建了定時器,并將他的ID?放入timerid指向的位置中。參數evp指定了定時器到期要產生的異步通知。如果evp為NULL,那么定時器到期會產生默認的信號,對?CLOCK_REALTIMER來說,默認信號就是SIGALRM。如果要產生除默認信號之外的其它信號,程序必須將?evp->sigev_signo設置為期望的信號碼。struct?sigevent?結構中的成員evp->sigev_notify說明了定時器到期時應該采取的行動。通常,這個成員的值為SIGEV_SIGNAL,這個值說明在定時器到期時,會產生一個信號。程序可以將成員evp->sigev_notify設為SIGEV_NONE來防止定時器到期時產生信號。

?

??? 如果幾個定時器產生了同一個信號,處理程序可以用?evp->sigev_value來區分是哪個定時器產生了信號。要實現這種功能,程序必須在為信號安裝處理程序時,使用struct?sigaction的成員sa_flags中的標志符SA_SIGINFO。

?

clock_id取值為以下:

CLOCK_REALTIME?:Systemwide?realtime?clock.

CLOCK_MONOTONIC:Represents?monotonic?time.?Cannot?be?set.

CLOCK_PROCESS_CPUTIME_ID?:High?resolution?per-process?timer.

CLOCK_THREAD_CPUTIME_ID?:Thread-specific?timer.

CLOCK_REALTIME_HR?:High?resolution?version?of?CLOCK_REALTIME.

CLOCK_MONOTONIC_HR?:High?resolution?version?of?CLOCK_MONOTONIC.

?

struct?sigevent

{

int?sigev_notify;?//notification?type

int?sigev_signo;?//signal?number

union?sigval???sigev_value;?//signal?value

void?(*sigev_notify_function)(union?sigval);

pthread_attr_t?*sigev_notify_attributes;

}

union?sigval

{

int?sival_int;?//integer?value

void?*sival_ptr;?//pointer?value

}

通過將evp->sigev_notify設定為如下值來定制定時器到期后的行為:

SIGEV_NONE:什么都不做,只提供通過timer_gettime和timer_getoverrun查詢超時信息。

SIGEV_SIGNAL:?當定時器到期,內核會將sigev_signo所指定的信號傳送給進程。在信號處理程序中,si_value會被設定會sigev_value。

SIGEV_THREAD:?當定時器到期,內核會(在此進程內)以sigev_notification_attributes為線程屬性創建一個線程,并且讓它執行sigev_notify_function,傳入sigev_value作為為一個參數

?

啟動一個定時器:

??? timer_create()所創建的定時器并未啟動。要將它關聯到一個到期時間以及啟動時鐘周期,可以使用timer_settime()。

int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspect *ovalue);

?

struct itimespec{

??? struct timespec it_interval;?

??? struct timespec it_value;???

};?

??? 如同settimer(),it_value用于指定當前的定時器到期時間。當定時器到期,it_value的值會被更新成it_interval 的值。如果it_interval的值為0,則定時器不是一個時間間隔定時器,一旦it_value到期就會回到未啟動狀態。timespec的結構提供了納秒級分辨率:

struct timespec{

??? time_t tv_sec;

??? long tv_nsec;??

};

??? 如果flags的值為TIMER_ABSTIME,則value所指定的時間值會被解讀成絕對值(此值的默認的解讀方式為相對于當前的時間)。這個經修改的行為可避免取得當前時間、計算“該時間”與“所期望的未來時間”的相對差額以及啟動定時器期間造成競爭條件。

??? 如果ovalue的值不是NULL,則之前的定時器到期時間會被存入其所提供的itimerspec。如果定時器之前處在未啟動狀態,則此結構的成員全都會被設定成0。

?

?

獲得一個活動定時器的剩余時間:

int?timer_gettime(timer_t?timerid,struct?itimerspec?*value);

?

取得一個定時器的超限運行次數:

??? 有可能一個定時器到期了,而同一定時器上一次到期時產生的信號還處于掛起狀態。在這種情況下,其中的一個信號可能會丟失。這就是定時器超限。程序可以通過調用timer_getoverrun來確定一個特定的定時器出現這種超限的次數。定時器超限只能發生在同一個定時器產生的信號上。由多個定時器,甚至是那些使用相同的時鐘和信號的定時器,所產生的信號都會排隊而不會丟失。

int?timer_getoverrun(timer_t?timerid);

??? 執行成功時,timer_getoverrun()會返回定時器初次到期與通知進程(例如通過信號)定時器已到期之間額外發生的定時器到期次數。舉例來說,在我們之前的例子中,一個1ms的定時器運行了10ms,則此調用會返回9。如果超限運行的次數等于或大于DELAYTIMER_MAX,則此調用會返回DELAYTIMER_MAX。

??? 執行失敗時,此函數會返回-1并將errno設定會EINVAL,這個唯一的錯誤情況代表timerid指定了無效的定時器。

?

刪除一個定時器:

int timer_delete (timer_t timerid);

??? 一次成功的timer_delete()調用會銷毀關聯到timerid的定時器并且返回0。執行失敗時,此調用會返回-1并將errno設定會 EINVAL,這個唯一的錯誤情況代表timerid不是一個有效的定時器。

?

例1:

void? handle()
{
?time_t t;
?char p[32];

?time(&t);
?strftime(p, sizeof(p), "%T", localtime(&t));

?printf("time is %sn", p);
}

?

int main()
{
?struct sigevent evp;
?struct itimerspec ts;
?timer_t timer;
?int ret;

?evp.sigev_value.sival_ptr = &timer;
?evp.sigev_notify = SIGEV_SIGNAL;
?evp.sigev_signo = SIGUSR1;
?signal(SIGUSR1, handle);

?ret = timer_create(CLOCK_REALTIME, &evp, &timer);
?if( ret )
??perror("timer_create");

?ts.it_interval.tv_sec = 1;
?ts.it_interval.tv_nsec = 0;
?ts.it_value.tv_sec = 3;
?ts.it_value.tv_nsec = 0;

?ret = timer_settime(timer, 0, &ts, NULL);
?if( ret )
??perror("timer_settime");

?while(1);
}

?

例2:

void? handle(union sigval v)
{
?time_t t;
?char p[32];

?time(&t);
?strftime(p, sizeof(p), "%T", localtime(&t));

?printf("%s thread %lu, val = %d, signal captured.n", p, pthread_self(), v.sival_int);
?return;
}

?

int main()
{
?struct sigevent evp;
?struct itimerspec ts;
?timer_t timer;
?int ret;

?memset?? (&evp,?? 0,?? sizeof?? (evp));
?evp.sigev_value.sival_ptr = &timer;
?evp.sigev_notify = SIGEV_THREAD;
?evp.sigev_notify_function = handle;
?evp.sigev_value.sival_int = 3;?? //作為handle()的參數

?ret = timer_create(CLOCK_REALTIME, &evp, &timer);
?if( ret)
??perror("timer_create");

?ts.it_interval.tv_sec = 1;
?ts.it_interval.tv_nsec = 0;
?ts.it_value.tv_sec = 3;
?ts.it_value.tv_nsec = 0;

?ret = timer_settime(timer, TIMER_ABSTIME, &ts, NULL);
?if( ret )
??perror("timer_settime");

?while(1);
}

總結

以上是生活随笔為你收集整理的POSIX定时器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。