Maison  >  Article  >  Tutoriel système  >  L'interface de minuterie la plus puissante vient de la série d'horloges POSIX, le saviez-vous ?

L'interface de minuterie la plus puissante vient de la série d'horloges POSIX, le saviez-vous ?

WBOY
WBOYavant
2024-03-10 11:40:031110parcourir

Le socket de minuterie le plus puissant provient de la série d'horloges POSIX. Les actions de création, d'initialisation et de suppression d'un minuteur sont divisées en trois fonctions différentes : timer_create() (créer un minuteur), timer_settime() (initialiser un minuteur) et timer_delete (le détruire). ).

Créer une minuterie :

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

Un processus peut créer un minuteur spécifique en appelant timer_create(). Le minuteur est unique à chaque processus et n'est pas hérité lors du fork. clock_id indique sur quelle horloge la minuterie est basée et *timerid charge l'ID de la minuterie créée. Cette fonction crée le minuteur et charge son ID à l'emplacement indiqué par timerid. Le paramètre evp spécifie la notification asynchrone à générer à l'expiration du timer. Si evp est NULL, alors l'expiration du temporisateur générera un signal par défaut pour CLOCK_REALTIMER, le signal par défaut est SIGALRM. Si vous souhaitez générer un signal autre que le signal Linux par défaut, le programme doit définir evp->sigev_signo sur le numéro de signal souhaité. Le membre evp->sigev_notify dans la structure structsigevent décrit l'action qui doit être entreprise à l'expiration du délai. Généralement, la valeur de ce membre est SIGEV_SIGNAL, ce qui indique qu'un signal sera généré à l'expiration du temporisateur. Le programme peut définir le membre evp->sigev_notify sur SIGEV_NONE pour éviter de générer un signal à l'expiration du délai.

Si plusieurs timers génèrent le même signal, le gestionnaire peut utiliser evp->sigev_value pour identifier quel timer a généré le signal. Pour implémenter ces fonctions, le programme doit utiliser l'identifiant SA_SIGINFO dans le membre sa_flags de structsigaction lors de l'installation d'un gestionnaire pour le signal.

La valeur de

clock_id est la suivante :

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
}

Personnalisez le comportement après l'expiration du délai en définissant evp->sigev_notify sur la valeur suivante :

Démarrer un chronomètre :

Le timer créé par timer_create() n'a pas été démarré. Pour l'associer à une heure d'expiration et à une période d'horloge de démarrage, utilisez 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; 
}; 

Tout comme settimer(), it_value est utilisé pour spécifier l'heure d'expiration actuelle de la minuterie. Lorsque le délai expire, la valeur de it_value sera mise à jour avec la valeur de it_interval. Si la valeur de it_interval est 0, le minuteur n'est pas un minuteur d'intervalle et reviendra à l'état non démarré une fois la valeur it_value expirée. La structure de timespec fournit un débit de code au niveau de la milliseconde :

struct timespec
{
time_t tv_sec;
long tv_nsec;
};

Si la valeur des drapeaux est TIMER_ABSTIME, la valeur de temps spécifiée par valeur sera analysée en valeur absolue (la méthode d'analyse par défaut pour cette valeur est relative à l'heure actuelle). Ce changement de comportement évite que des conditions de concurrence ne soient provoquées lors de la récupération de l'heure actuelle, du calcul de la différence relative entre cette heure et l'heure future souhaitée et du démarrage des chronomètres.

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

Si la valeur de ovalue n'est pas NULL, l'heure d'expiration précédente de la minuterie sera stockée dans la spécification itimer fournie. Si le timer n'a pas été démarré auparavant, tous les membres de cette structure seront mis à 0.

Obtenez le temps restant d'une minuterie active :

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

Obtenez le nombre de dépassements d'une minuterie :

有可能一个定时器到期了,而同一定时器上一次到期时形成的讯号还处于挂起状态。在这些情况下,其中的一个讯号可能会遗失。这就是定时器超限。程序可以通过调用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(timer,0,&ts,NULL);

si(ret)

perror("timer_settime");

pendant(1);

例2:

voidhandle(unionsigvalv)

time_tt;

charpe[32];

heure(&t);

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

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

retour ;

intmain()

structsigeventevp;

structitimerspects;

timer_ttimer;

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);

si(ret)

perror("timer_create");

_sec=1;

_nsec=0;

_sec=3;

_nsec=0;

ret=timer_settime(timer,TIMER_ABSTIME,&ts,NULL);

si(ret)

perror("timer_settime");

pendant(1);

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer