The most powerful timer socket comes from the POSIX clock series. The actions of creating, initializing and deleting a timer are divided into three different functions: timer_create() (create timer), timer_settime() (initialize timer) device) and timer_delete (destroy it).
Create a timer:
<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)</span>
A process can create a specific timer by calling timer_create(). The timer is unique to each process and is not inherited when forking. clock_id indicates which clock the timer is based on, and *timerid loads the ID of the created timer. This function creates the timer and loads its ID into the location pointed to by timerid. The parameter evp specifies the asynchronous notification to be generated when the timer expires. If evp is NULL, then the timer expiration will generate a default signal. For CLOCK_REALTIMER, the default signal is SIGALRM. If you want to generate a signal other than the default signal linux, the program must set evp->sigev_signo to the desired signal number. The member evp->sigev_notify in the structsigevent structure describes the action that should be taken when the timer expires. Generally, the value of this member is SIGEV_SIGNAL, which indicates that a signal will be generated when the timer expires. The program can set the member evp->sigev_notify to SIGEV_NONE to avoid generating a signal when the timer expires.
If several timers generate the same signal, the handler can use evp->sigev_value to determine which timer generated the signal. To implement these functions, the program must use the identifier SA_SIGINFO in the member sa_flags of structsigaction when installing a handler for the signal.
The value of clock_id is as follows:
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 }
Customize the behavior after the timer expires by setting evp->sigev_notify to the following value:
Start a timer:
The timer created by timer_create() has not been started. To associate it with an expiration time and start clock period, use 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; };
Just like settimer(), it_value is used to specify the current timer expiration time. When the timer expires, the value of it_value will be updated to the value of it_interval. If the value of it_interval is 0, the timer is not an interval timer and will return to the unstarted state once the it_value expires. The structure of timespec provides millisecond-level code rate:
struct timespec { time_t tv_sec; long tv_nsec; };
If the value of flags is TIMER_ABSTIME, the time value specified by value will be parsed into an absolute value (the default parsing method for this value is relative to the current time). This changed behavior prevents race conditions during retrieval of the current time, calculation of the relative difference between this time and the desired future time, and starting timers.
If the value of ovalue is not NULL, the previous timer expiration time will be stored in the provided itimerspec. If the timer was not started before, all members of this structure will be set to 0.
Get the remaining time of an active timer:
<span style="font-family:SimSun;font-size:18px;color:#ff0000">int timer_gettime(timer_t timerid,struct itimerspec *value);</span>
Get the number of overrun runs of a timer:
有可能一个定时器到期了,而同一定时器上一次到期时形成的讯号还处于挂起状态。在这些情况下,其中的一个讯号可能会遗失。这就是定时器超限。程序可以通过调用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(timer,0,&ts,NULL);
if(ret)
perror("timer_settime");
while(1);
例2:
voidhandle(unionsigvalv)
time_tt;
charp[32];
time(&t);
strftime(p,sizeof(p),"%T",localtime(&t));
printf("%sthread%lu,val=%d,signalcaptured./n",p,pthread_self(),v.sival_int);
return;
intmain()
structsigeventevp;
structitimerspects;
timer_ttimer;
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);
if(ret)
perror("timer_create");
_sec=1;
_nsec=0;
_sec=3;
_nsec=0;
ret=timer_settime(timer,TIMER_ABSTIME,&ts,NULL);
if(ret)
perror("timer_settime");
while(1);
The above is the detailed content of The most powerful timer interface comes from the POSIX clock series, did you know?. For more information, please follow other related articles on the PHP Chinese website!