定时器小结 setitimer/getitimer Or timer_settime/timer_gettime

    最近在移植Python至VxWorks,小小菜鸟遇到了粉多麻烦,其中定时器相关的就可独占一章。

    首先,对于定时器中使用的数据结构,在Python中使用的数据结构为itimerval,通过查阅VxWorks手册及源码可知,VxWorks支持的数据结构为itimerspec,如下:

    itimerval结构在UNIX/LINUX中定义,定义如下:

Struct itimerval{

Struct timeval it_interval; /* nextvalue:下一次触发所需的时间*/

Struct timeval it_value;  /*current value:目前距离触发时间点剩余的时间*/

};

Struct timeval{

Long tv_sec; /* seconds */

Long tv_usec; /*microseconds*/

};

    查阅VxWorks源码后认为,该数据结构与VxWorks中的itimespec结构意义相同,该结构在time.h中定义,VxWorks中定义如下:

structitimerspec

{

    struct timespecit_interval;        /* timer period(reload value) */

    struct timespecit_value;                /*timer expiration */

};

structtimespec

{                                           /*interval = tv_sec*10**9 + tv_nsec */

    time_t tv_sec;                        /*seconds */

    long tv_nsec;                        /*nanoseconds (0 - 1,000,000,000) */

};

    修改完毕并编译APP通过后下载时出现问题,提示_setitimer, _getitimer符号出错,原来python代码中定时器使用的是setitimer和getitimer函数,显然,这两个函数在VxWorks系统中是不支持的,不仅手册中没有该函数介绍,就连VxWorks源码中说明setitimer的地方实际使用的也是timer_settime函数。

1 setitimer()/getitimer()

Setitimer/getitimer为Linux的API,并非C语言的标准库。函数定义为:

#include <sys/time.h>

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value));

intgetitimer(int which, struct itimerval *curr_value);

其中,

getitimer获取which指定的定时器的值并填入curr_value字段中。

setitimer设定指定的定时器,即设置vlaue的值。各参数说明如下:

第一个参数:which为定时器类型,setitimer支持3种类型的定时器:

ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。

ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。 (

decrements only when the process is executing, anddelivers SIGVTALRM upon expiration

ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。(

decrements both when the process executes and when thesystem is executing on behalf of the process. Coupled with ITIMER_VIRTUAL, this timer is usually usedto profile the time spent by the application in user and kernel space. SIGPROF is delivered upon expiration.

第二个参数:new_value,表示设定的定时器值;

第三个参数:old_value ,常设为NULL,如果不为NULL,用来保存先前的定时器值,

返回值:调用成功返回0,否则返回-1

说明:setitimer()基于进程,且不由fork()继承而来。(A child created via fork(2) does not inherit its parent's interval timers.Interval timers are preserved across an execve(2).

POSIX.1 leaves the interaction between setitimer() and the three interfaces alarm(2), sleep(3), and usleep(3) unspecified.

Bugs

The generation and delivery of a signal are distinct, and only oneinstance of each of the signals listed above may be pending for a process.Under very heavy loading, an ITIMER_REALtimer may expire before the signal from a previous expiration has beendelivered. The second signal in such an event will be lost.

On Linux kernels before 2.6.16, timer values are represented injiffies. If a request is made set a timer with a value whose jiffiesrepresentation exceeds MAX_SEC_IN_JIFFIES(defined in include/linux/jiffies.h),then the timer is silently truncated to this ceiling value. On Linux/i386(where, since Linux 2.6.13, the default jiffy is 0.004 seconds), this meansthat the ceiling value for a timer is approximately 99.42 days. Since Linux2.6.16, the kernel uses a different internal representation for times, and thisceiling is removed.

On certain systems (including i386), Linux kernels before version2.6.12 have a bug which will produce premature timer expirations of up to onejiffy under some circumstances. This bug is fixed in kernel 2.6.12.

POSIX.1-2001 says that setitimer() should fail if a tv_usecvalue is specified that is outside of the range 0 to 999999. However, inkernels up to and including 2.6.21, Linux does not give an error, but insteadsilently adjusts the corresponding seconds value for the timer. From kernel2.6.22 onward, this nonconformance has been repaired: an improper tv_usec value results in an EINVAL error.

源文档 <http://linux.die.net/man/2/setitimer>

 

2, timer_settime/timer_gettime

VxWorks系统中支持的定时器函数为timer_settime/timer_gettime, 这两个函数是POSIX定时器,在POSIX系统中应使用该函数替代上面说的setitimer/getitimer。函数定义如下:

#include <time.h>

int timer_settime(timer_t timerid, int flags,
                  const struct itimerspec*new_value,
                  struct itimerspec *old_value);
int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
Timer_settime() arms ordisarms 由timerid指定的定时器。参数取值如下:

第一个参数:timerid, 指定定时器ID;

第二个参数:flags,定时器类型,取值可为TIMER_ABSTIME/CLOCK_REALTIME。

说明:

By default, the initial expiration time specified in new_value->it_value is interpreted relative to the current time on the timer'sclock at the time of the call. This can be modified by specifying TIMER_ABSTIME in flags, in which case new_value->it_value isinterpreted as an absolute value as measured on the timer's clock; that is, thetimer will expire when the clock value reaches the value specified by new_value->it_value. If the specified absolute time has already passed, thenthe timer expires immediately, and the overrun count (see timer_getoverrun(2)) will be setcorrectly.

If the value of the CLOCK_REALTIMEclock is adjusted while an absolute timer based on that clock is armed, thenthe expiration of the timer will be appropriately adjusted. Adjustments to the CLOCK_REALTIME clock have no effect on relativetimers based on that clock.

第三个参数:new_value, 指定定时器的新初始值和间隔;

第四个参数:old_value, 取值常为NULL,若不为NULL,它返回定时器的前一个值。(

previous interval of the timer (in old_value->it_interval) and the amount of time until thetimer would previously have next expired (in old_value->it_value).

Timer_gettime返回定时器截止的时间,说明如下:

timer_gettime() returns thetime until next expiration, and the interval, for the timer specified by timerid, in the buffer pointed to by curr_value. The time remaining until the nexttimer expiration is returned in curr_value->it_value;this is always a relative value, regardless of whether the TIMER_ABSTIME flag was used when arming thetimer. If the value returned in curr_value->it_valueis zero, then the timer is currently disarmed. The timer interval is returnedin curr_value->it_interval. If thevalue returned in curr_value->it_intervalis zero, then this is a "one-shot" timer.

返回值:

On success, timer_settime()and timer_gettime() return 0. On error,-1 is returned, and errno is set toindicate the error.

源文档 <http://linux.die.net/man/2/timer_gettime>

 

说明:在使用定时器前,需要先创建定时器(timer_create),使用完定时器后,还需删除定时器。

#include<signal.h>
#include <time.h>

inttimer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);

函数功能:为进程创建一个新定时器。

参数说明:

第一个参数:clockid, 指定新定时器用于度量时间的始终,可以为下列值:

CLOCK_REALTIME

A settable system-wide real-time clock.

CLOCK_MONOTONIC

A nonsettable monotonically increasing clock thatmeasures time from some unspecified point in the past that does not changeafter system startup.

CLOCK_PROCESS_CPUTIME_ID(since Linux 2.6.12)

A clock that measures (user and system) CPU timeconsumed by (all of the threads in) the calling process.

CLOCK_THREAD_CPUTIME_ID (sinceLinux 2.6.12)

A clock that measures (user and system) CPU timeconsumed by the calling thread

第二个参数:sevp,指定当定时器时间到期时触发的信号事件sigevent,sevp.sigev_notify取值如下:

SIGEV_NONE

Don't asynchronously notify when the timerexpires. Progress of the timer can be monitored using timer_gettime(2).

SIGEV_SIGNAL

Upon timer expiration, generate the signalsigev_signo for the process. See sigevent(7) for general details. The si_code field of the siginfo_tstructure will be set to SI_TIMER. At any point in time, at most one signal is queued to theprocess for a given timer; see timer_getoverrun(2) for moredetails.

SIGEV_THREAD

Upon timer expiration, invoke sigev_notify_function as if it were the start function of a new thread. See sigevent(7) for details.

SIGEV_THREAD_ID(Linux-specific)

As for SIGEV_SIGNAL, but the signalis targeted at the thread whose ID is given in sigev_notify_thread_id,which must be a thread in the same process as the caller. The sigev_notify_thread_id field specifies a kernel thread ID, that is, the valuereturned by clone(2) or gettid(2). This flag is only intended for use by threadinglibraries.

Specifying sevpas NULL is equivalent to specifying a pointer to a sigevent structure in which sigev_notifyis SIGEV_SIGNAL, sigev_signo is SIGALRM,and sigev_value.sival_int is the timerID

第三个参数:timerid,定时器ID,为函数返回值,必须是一个非空的指针,且在进程中唯一。

返回值:
Onsuccess, timer_create() returns 0, and the ID of the newtimer is placed in *timerid. On failure, -1 is returned,and errno is set to indicate the error

源文档 <http://linux.die.net/man/2/timer_create>

 

你可能感兴趣的:(定时器小结 setitimer/getitimer Or timer_settime/timer_gettime)