首頁  >  文章  >  系統教程  >  最強大的定時器介面來自POSIX時脈系列,你知道嗎?

最強大的定時器介面來自POSIX時脈系列,你知道嗎?

WBOY
WBOY轉載
2024-03-10 11:40:031110瀏覽

最強悍的定時器插口來自POSIX時鐘系列,其創建、初始化以及刪除一個定時器的行動被分為三個不同的函數:timer_create()(創建定時器)、timer_settime()(初始化定時器)以及timer_delete(銷毀它)。

建立一個定時器:

<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)</span>

進程可以透過呼叫timer_create()來建立特定的定時器,定時器是每位進程自己的,不是在fork時承繼的。 clock_id說明定時器是基於那個時鐘的,*timerid裝載的是被建立的計時器的ID。函數建立了定時器,並將他的ID裝入timerid指向的位置。參數evp指定了定時器到期要形成的非同步通知。假如evp為NULL,這麼定時器到期會形成預設的訊號,對CLOCK_REALTIMER來說,預設訊號就是SIGALRM。如果要形成除預設訊號之外的其它訊號號linux,程式必須將evp->sigev_signo設定為期望的信號碼。 structsigevent結構中的成員evp->sigev_notify說明了定時器到期時應採取的行動。一般,這個成員的值為SIGEV_SIGNAL,這個值說明在定時器到期時,會形成一個訊號。程式可以將成員evp->sigev_notify設為SIGEV_NONE來避免定時器到期時形成訊號。

假如幾個定時器形成了同一個訊號,處理程序可以用evp->sigev_value來分辨是那個定時器形成了訊號。要實現這些功能,程式必須在為訊號安裝處理程序時,使用structsigaction的成員sa_flags中的標誌符SA_SIGINFO。

clock_id取值為以下:

struct sigevent
{
<span>	</span>int sigev_notify; //notification type
<span>	</span>int sigev_signo; //signal number
<span>	</span>union sigval sigev_value; //signal value
<span>	</span>void (*sigev_notify_function)(union sigval);
<span>	</span>pthread_attr_t *sigev_notify_attributes;
}
union sigval
{
<span>	</span>int sival_int; //integer value
<span>	</span>void *sival_ptr; //pointer value
}

透過將evp->sigev_notify設定為以下值來定制定時器到期後的行為:

啟動一個計時器:

timer_create()所建立的定時器並未啟動。要將它關聯到一個到期時間以及啟動時脈週期,可以使用timer_settime()。

<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspect *ovalue);</span>

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所指定的時間值會被剖析成絕對值(此值的預設的剖析方法為相對於當前的時間)。這個經更改的行為可防止取得當前時間、計算「該時間」與「所期望的未來時間」的相對差額以及啟動定時器期間導致競爭條件。

定时器程序设计实验报告_linux 定时器程序_定时器程序编写

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

取得一個活動計時器的剩餘時間:

<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_gettime(timer_t timerid,struct itimerspec *value);</span>

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

有可能一个定时器到期了,而同一定时器上一次到期时形成的讯号还处于挂起状态。在这些情况下,其中的一个讯号可能会遗失。这就是定时器超限。程序可以通过调用timer_getoverrun来确定一个特定的定时器出现这些超限的次数。定时器超限只能发生在同一个定时器形成的讯号上。由多个定时器linux 定时器程序,甚至是这些使用相同的时钟和讯号的定时器,所形成的讯号就会排队而不会遗失。

<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_delete (timer_t timerid);</span>

执行成功时,timer_getoverrun()会返回定时器初次到期与通知进程(比如通过讯号)定时器已到期之间额外发生的定时器到期次数。举例来说linux 定时器程序,在我们之前的事例中,一个1ms的定时器运行了10ms,则此调用会返回9。假如超限运行的次数等于或小于DELAYTIMER_MAX,则此调用会返回DELAYTIMER_MAX。

执行失败时,此函数会返回-1并将errno设定会EINVAL,这个惟一的错误情况代表timerid指定了无效的定时器。

删掉一个定时器:

<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_delete (timer_t timerid);</span>

一次成功的timer_delete()调用会销毁关联到timerid的定时器而且返回0。执行失败时,此调用会返回-1并将errno设定会EINVAL,这个惟一的错误情况代表timerid不是一个有效的定时器。

例1:

voidhandle()

time_tt;

charp[32];

time(&t);

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

printf("timeis%s/n",p);

intmain()

structsigeventevp;

structitimerspects;

timer_ttimer;

intret;

evp.sigev_value.sival_ptr=&timer;

evp.sigev_notify=SIGEV_SIGNAL;

evp.sigev_signo=SIGUSR1;

定时器程序设计实验报告_定时器程序编写_linux 定时器程序

signal(SIGUSR1,handle);

ret=timer_create(CLOCK_REALTIME,&evp,&timer);

if(ret)

perror("timer_create");

_sec=1;

_nsec=0;

_sec=3;

_nsec=0;

ret=timer_settime(計時器,0,&ts,NULL);

如果(ret)

perror("timer_settime");

同時(1);

例2:

voidhandle(unionsigvalv)

time_tt;

charp[32];

時間(&t);

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

printf("%sthread%lu,val=%d,signalcaptured./n",p,pthread_self(),v.sival_int);

###返回;###

intmain()

structsigeventevp;

structitimerspects;

timer_timer;

intret;

memset(&evp,0,sizeof(evp));

定时器程序设计实验报告_linux 定时器程序_定时器程序编写#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);

如果(ret)

perror("timer_create");

_秒=1;

_nsec=0;

_秒=3;

_nsec=0;

ret=timer_settime(定時器,TIMER_ABSTIME,&ts,NULL);

如果(ret)

perror("timer_settime");

同時(1);

以上是最強大的定時器介面來自POSIX時脈系列,你知道嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:itcool.net。如有侵權,請聯絡admin@php.cn刪除