最強悍的定時器插口來自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所指定的時間值會被剖析成絕對值(此值的預設的剖析方法為相對於當前的時間)。這個經更改的行為可防止取得當前時間、計算「該時間」與「所期望的未來時間」的相對差額以及啟動定時器期間導致競爭條件。
#假如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;
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));
#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中文網其他相關文章!