Maison  >  Article  >  Tutoriel système  >  choc! Les minuteries ont en fait tellement de fonctionnalités, le saviez-vous ?

choc! Les minuteries ont en fait tellement de fonctionnalités, le saviez-vous ?

WBOY
WBOYoriginal
2024-06-14 09:14:49899parcourir

choc! Les minuteries ont en fait tellement de fonctionnalités, le saviez-vous ?

Pendant le processus de communication des données, vous rencontrerez des exigences de format concernant l'heure d'envoi des données. Par conséquent, afin de sélectionner différents temporisateurs en fonction des exigences réelles de l’application, il est nécessaire de prendre en compte les caractéristiques de plusieurs temporisateurs d’application.

Référence de l'article sur la minuterie

De manière générale, oui,

1. dormir, dormir et nanosommeil

sleep() et nanosleep() provoquent tous deux une mise en veille du processus pendant un certain temps avant d'être réveillé, et leurs implémentations sont complètement différentes.

Linux ne fournit pas l'appel système sleep(). sleep() est implémenté dans la fonction de bibliothèque. Il définit l'heure de rapport en appelant alarm() et appelle sigsuspend() pour suspendre le processus sur le signal SIGALARM sleep(). ne peut être précis qu’au deuxième niveau.

nanosleep() est un appel système sous Linuxlinux timer precision Il est implémenté à l'aide d'un timer. Cet appel met le processus appelant en veille et ajoute un timer de type timer_list à la file d'attente time_list, y compris le wake-. le temps de fonctionnement et les fonctions exécutées après le réveil. La fonction d'exécution de la minuterie ajoutée via nanosleep() ne complète que la fonction de réveil du processus en cours. Le système détecte régulièrement ces files d'attente grâce à un certain mécanisme (par exemple, après avoir été piégé dans le noyau via un appel système et avant de revenir du noyau au mode utilisateur, il doit vérifier si la tranche de temps du processus en cours est épuisée, et si tel est le cas, appelez la fonction planning() pour replanifier, la file d'attente du minuteur sera détectée dans cette fonction, et cette détection sera également effectuée avant le retour de l'interruption lente). Si le temps de synchronisation est dépassé, la fonction spécifiée par le minuteur. sera exécuté pour réveiller le processus appelant. En fait, comme la tranche de temps système peut être perdue, la précision de nanosleep() n'est pas très élevée.

linux高精度定时器精度_linux时钟精度_linux 定时器 精度

alarm() est également implémenté par le système d'exploitation Red Flag Linux via une minuterie, et sa précision n'est précise qu'au deuxième niveau. De plus, la fonction d'exécution de la minuterie qu'elle définit est d'envoyer le signal SIGALRM au processus en cours. temps spécifié.

2. Utilisez le sémaphore SIGALRM+alarm()

Bien que la méthode d'alarme soit très bonne, la précision de ces méthodes peut atteindre une seconde, mais il est difficile d'atteindre une précision supérieure à une seconde. Le mécanisme de sémaphore du système *nix est utilisé. Tout d'abord, enregistrez la fonction de traitement du sémaphore SIGALRM, appelez alarm() et définissez la largeur de synchronisation. Le code est le suivant :

.

linux高精度定时器精度_linux 定时器 精度_linux时钟精度

//设置一个1s延时信号,再注册一个
#include 
#include 
void timer(int sig)
{
if(SIGALRM == sig)
{
printf("timern");
alarm(1); //重新继续定时1s
}

return ;
}
int main()
{
signal(SIGALRM, timer); //注册安装信号

alarm(1); //触发定时器

getchar();

return 0;
}

3. Utilisez le mécanisme RTC

Le mécanisme

RTC utilise le mécanisme RealTimeClock fourni par le matériel du système, en lisant le matériel RTC /dev/rtc et en définissant la fréquence RTC via ioctl(). Ces méthodes sont plus pratiques Précision de la minuterie Linux. Le RTC fourni par le matériel du système, la précision réglable et le code particulièrement élevé sont les suivants :

linux 定时器 精度_linux时钟精度_linux高精度定时器精度

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char* argv[])
{
unsigned long i = 0;
unsigned long data = 0;
int retval = 0;
int fd = open ("/dev/rtc", O_RDONLY);

if(fd < 0)
{
perror("open");
exit(errno);
}

/*Set the freq as 4Hz*/
if(ioctl(fd, RTC_IRQP_SET, 1) < 0)
{
perror("ioctl(RTC_IRQP_SET)");
close(fd);
exit(errno);
}
/* Enable periodic interrupts */
if(ioctl(fd, RTC_PIE_ON, 0) < 0)
{
perror("ioctl(RTC_PIE_ON)");
close(fd);
exit(errno);
}

for(i = 0; i < 100; i++)
{
if(read(fd, &data, sizeof(unsigned long)) < 0)
{
perror("read");
close(fd);
exit(errno);

}
printf("timern");
}
/* Disable periodic interrupts */
ioctl(fd, RTC_PIE_OFF, 0);
close(fd);

return 0;
}

Cette méthode nécessite que le système dispose d'un outil de création de disque de démarrage Linux de périphérique RTC. Notre 1860 dispose de deux RTC dans le LC1160 du module de gestion de l'alimentation, et il n'y a pas de prise en charge du mot de contrôle RTC_IRQP_SET dans le pilote. Le pilote doit être ajouté plus tard.

4、使用select()

能精确到1us,目前精确定时的最流行方案。通过使用select(),来设置定时器;原理借助select()方式的第5个参数,第一个参数设置为0,三个文件描述符集都设置为NULL,第5个参数为时间结构体,代码如下:

#include 
#include 
#include 
#include 
/*seconds: the seconds; mseconds: the micro seconds*/
void setTimer(int seconds, int mseconds)
{
struct timeval temp;

temp.tv_sec = seconds;
temp.tv_usec = mseconds * 1000;

select(0, NULL, NULL, NULL, &temp);
printf("timern");

return ;
}
int main()
{
int i;

for(i = 0 ; i < 100; i++)
setTimer(1, 0);

return 0;
}

结果是,每隔1s复印一次,复印100次。

select定时器是阻塞的,在等待时间到来之前哪些都不做。要定时可以考虑再开一个线程来做。

最终,下层应用程序的定时器的京都是内核决定的,这几个定时器的使用方式,尽管理论上可以精确到微妙,虽然,我分别在微妙级测试的时侯,偏差还是很大的,取决于,当时的cpu和进程的调度,等等。。。。

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn