Comment mettre en œuvre un "thread-safe" timer sur linux?
Comme nous le savons, faire les choses dans les gestionnaires de signaux est vraiment mauvais, parce qu'ils s'exécutent dans une interruption comme contexte. C'est tout à fait possible que les différentes écluses (y compris la fonction malloc() verrou de segment!) la tenue de la gestionnaire de signal est appelé.
Je tiens donc à mettre en œuvre un "thread-safe" timer sans l'aide du signal mécanisme.
Comment puis-je faire?
Désolé, en fait, je ne suis pas attendre de réponses au sujet de thread-safe, mais des réponses au sujet de la mise en œuvre d'une minuterie sur Unix ou Linux, qui est thread-safe.
Vous avez une confusion entre le code réentrant, nécessaire pour gérer les OS jmp-ing pour le fil conducteur DE LA 1 & SEUL FIL, et ensuite revenir à la très prochaine instruction dans ce thread, et une POSIX minuteur qui indique à l'aide d'un système d'exploitation générés par thread. Le plus tard est assez inutile, parce que vous ne savez pas où dans votre thread principal de l'OS informera spontanément par la génération d'un nouveau fil pour le signal. Ainsi, vous ne pouvez pas verrouiller et déverrouiller les exclusions mutuelles requises pour protéger les ressources partagées. Utiliser des signaux. Les Threads ne fonctionne que si le principal ne fait rien mais attendre sur le fil. C'est à dire: recrée sleep();
OriginalL'auteur dragonfly | 2009-03-23
Vous devez vous connecter pour publier un commentaire.
Utilisation usleep(3) ou sleep(3) dans votre fil. Cela va bloquer le thread jusqu'à l'expiration de ce délai.
Si vous avez besoin d'attendre sur les I/O et un minuteur expire avant l'I/O est prêt, utilisez select(2), poll(2) ou epoll(7) avec un délai d'attente.
Si vous avez encore besoin d'utiliser un gestionnaire de signal, créer un canal avec tuyau(2), faire un blocage de la lecture sur le côté lecture dans votre fil, ou utiliser select/poll/epoll à attendre qu'il soit prêt, et d'écrire un octet à l'écriture, à la fin de votre tuyau dans le gestionnaire de signal à écrire(2). Il n'a pas d'importance ce que vous écrivez à la pipe - l'idée est de simplement obtenir votre thread à se réveiller. Si vous voulez pour le multiplexage des signaux sur l'un tuyau, écrire le numéro du signal ou une autre ID de la pipe.
Si je veux faire quelque chose(peut-être pas complète) pendant les intervalles(pas dans un autre thread), comment dois-je utiliser ces
sleep
-comme APIs?Vous n'avez pas fourni suffisamment de détails de ce que vous voulez faire. Si vous avez du travail à faire, pourquoi dormez-vous?
normalement, ces emplois " moment de l'exécution est inférieur à l'intervalle de temps(disons
10s
), mais ces travaux ne peuvent exécuter une fois sur chaque intervalle, j'ai donc dormir un certain temps (après execute) pour attendre le prochain intervalle de venir.Je vous suggère de poser votre propre question sur ce site, plutôt que d'essayer de l'obtenir répondu dans les commentaires.
OriginalL'auteur camh
Vous devriez probablement utiliser quelque chose comme
pthreads
, les threads POSIX bibliothèque. Il fournit non seulement les fils eux-mêmes, mais aussi base de primitives de synchronisation comme les mutex (écluses), les conditions, les sémaphores. Voici un tutoriel que j'ai trouvé qui semble être décent:http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Pour ce que ça vaut, si vous êtes très familier avec la programmation multithread, il pourrait être un peu plus facile à apprendre en Java ou en Python, si vous connaissez un de ceux, que dans C.
L'OP a demandé comment mettre en œuvre une minuterie sans l'aide de signaux. Les Threads ne sont pas des signaux. Je ne vois rien à suggérer qu'il était à l'aide de threads...
OriginalL'auteur David Z
Je pense que l'habitude moyen de contourner les problèmes que vous décrivez est de rendre les gestionnaires de signaux de faire un minimum de travail. E. g. la définition de certains timer_expired drapeau. Vous avez un peu de fil qui vérifie régulièrement si l'indicateur a été défini, et le travail réel.
Si vous ne voulez pas utiliser des signaux, je suppose que vous auriez à faire un fil de sommeil ou occupé-attendre que le temps spécifié.
OriginalL'auteur janneb
Utiliser une Posix minuteur d'intervalle, et de le faire avertir par un signal. À l'intérieur du gestionnaire de signal fonction presque aucun de C fonctions comme printf() peut être utilisée, comme ils ne sont pas ré-entrant.
Utiliser un seul indicateur global, a déclaré statique volatils pour votre gestionnaire de signal à manipuler. Le gestionnaire doit littéralement cette ligne de code, et RIEN d'autre; Ce drapeau devrait influer sur les flux de contrôle d'ailleurs dans le 1 & Seul fil dans le programme.
Michael Kerrisk de Linux, l'Interface de Programmation d' a des exemples de ces deux méthodes, et un peu plus, mais les exemples qui viennent avec beaucoup de ses fonctions privées vous devez vous mettre au travail, et les exemples soigneusement éviter de nombreux pièges qu'ils doivent explorer, donc pas très grande.
À l'aide de la Poxix intervalle de minuterie qui informe via un thread rend tout beaucoup plus, et AFAICT, de la notification de la méthode est à peu près inutile. Je dis à peu près, car je suis en permettant qu'il peut y avoir CERTAINS cas où ne rien faire dans le main() thread, et tout le thread de gestion est utile, mais je ne peux pas penser à de tels cas.
OriginalL'auteur user2548100