[LINUX] Programmation asynchrone avec libev

libev

libev est une bibliothèque qui gère le traitement asynchrone et est également utilisée dans node.js et ainsi de suite. À l'origine, le système Unix avait un processus asynchrone appelé select () qui gère les descripteurs de fichiers, mais cela limitait le nombre de descripteurs de fichiers pouvant être surveillés. Après cela, un nombre illimité de poll () a été développé, epoll () qui a accéléré poll () a été développé sous Linux et KQUEUE a été développé en BSD. Et une bibliothèque appelée libev a été développée pour absorber ces différences.

Installation

brew install libev

La version actuelle sera installée à l'emplacement suivant: Cette entrée traite ce chemin tel quel, sans passer par le chemin de la bibliothèque.

/usr/local/Cellar/libev/4.15/

paramètres xcode

Ajoutez ce qui suit aux «chemins de recherche d'en-tête» dans les paramètres de construction du projet.

/usr/local/Cellar/libev/4.15/include/

Ajoutez ce qui suit aux "Chemins de recherche de la bibliothèque" dans les paramètres de construction du projet.

/usr/local/Cellar/libev/4.15/lib/

Ajoutez ce qui suit à «Liaison» dans les paramètres de construction du projet.

-lev
-ObjC
-all_load

Utilisation de base

Déclarez d'abord l'objet de boucle d'événement. Déclarez ensuite un objet de surveillance pour le type d'événement que vous souhaitez surveiller et associez le rappel au descripteur de fichier. Enfin, il démarre la boucle en même temps que l'association de la boucle d'événement à l'objet watch.

Ce qui suit est une légère modification de l'échantillon officiel.

#include <ev.h>
#include <iostream>

static void stdin_cb (EV_P_ ev_io *w, int revents)
{
    std::cout << "stdin ready\n";
    
    // I/Dissocier O de la boucle.
    ev_io_stop (EV_A_ w);
    
    //Briser la boucle des événements.
    ev_unloop (EV_A_ EVUNLOOP_ALL);
}

static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
    std::cout << "timeout\n";

    //Arrêtez le chronomètre.
    ev_timer_stop (EV_A_ w);
    
    //Briser la boucle des événements.
    ev_unloop (EV_A_ EVUNLOOP_ONE);
}

int main(int argc, const char * argv[])
{
    //Créer une boucle d'événements.
    struct ev_loop *loop = ev_loop_new (0);

    // I/Ô objet de montre.
    ev_io stdin_watcher;
    
    // I/Pour les objets O watch
    //Associer des rappels aux FD avec des types d'événements.
    ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
    
    // I/Associer une boucle d'événement à un objet O watch.
    ev_io_start (loop, &stdin_watcher);


    //Créer un objet minuterie.
    ev_timer timeout_watcher;
    
    //Associer un rappel à un objet timer et spécifier un timeout(Répéter dans 5 secondes 0).
    ev_timer_init (&timeout_watcher, timeout_cb, 5, 0.);
    
    //Associer une boucle d'événements à un objet timer.
    ev_timer_start (loop, &timeout_watcher);
    
    //Début de boucle.
    ev_loop (loop, 0);
    
    std::cout << "end¥n";
    
    //Supprimer la boucle d'événements créée
    ev_loop_destroy(loop);
    
    return 0;
}

Puisque vous ne pouvez pas interagir avec la ligne de commande avec xcode, essayez de créer avec gcc en utilisant la méthode suivante.

# gcc -o test test.cpp -lev -I/usr/local/Cellar/libev/4.15/include/ -L/usr/local/Cellar/libev/4.15/lib/ -lstdc++

Créer une boucle d'événements

L'exemple officiel utilise ev_default_loop (), mais il ne semble pas être thread-safe, donc dans l'exemple ci-dessus, nous avons créé une boucle d'événement avec ev_loop_new (0) et l'avons détruite avec ev_loop_destroy (boucle).

L'argument spécifie le processus asynchrone à utiliser lors de la création de cette boucle d'événements. La valeur par défaut est 0, qui est définie automatiquement.

Technologie asynchrone utilisée par libev

Vous pouvez voir ce qui est utilisé sur le backend avec la méthode suivante.

unsigned int ev_supported_backends ()
  EVBACKEND_SELECT  = 0x00000001U, /* about anywhere */
  EVBACKEND_POLL    = 0x00000002U, /* !win */
  EVBACKEND_EPOLL   = 0x00000004U, /* linux */
  EVBACKEND_KQUEUE  = 0x00000008U, /* bsd */
  EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
  EVBACKEND_PORT    = 0x00000020U, /* solaris 10 */
  EVBACKEND_ALL     = 0x0000003FU, /* all known backends */
  EVBACKEND_MASK    = 0x0000FFFFU  /* all future backends */

Vous pouvez obtenir le traitement asynchrone recommandé avec la méthode suivante.

unsigned int ev_recommended_backends();

Événements pouvant être surveillés

Ce qui peut être géré dépend du type d'objet de surveillance.

EV_READ EV_WRITE EV_TIMEOUT EV_PERIODIC EV_SIGNAL EV_CHILD EV_STAT EV_IDLE EV_PREPARE EV_CHECK EV_EMBED EV_FORK EV_ASYNC EV_ERROR

Type d'objet observé

ev_io ev_timer ev_periodic ev_signal ev_stat ev_idle ev_embed ev_fork ev_async

La prochaine fois, je traiterai des sockets.

Recommended Posts

Programmation asynchrone avec libev # 2
Programmation asynchrone avec libev
Programmation asynchrone avec libev # 3
3. 3. Programmation IA avec Python
Programmation Python avec Atom
Programmation compétitive avec python
Programmation Shader avec pyOpenGL
Programmation linéaire avec PuLP
Programmation avec Python Flask
Essayez de programmer avec un shell!
Essayez la programmation GUI avec Hy
Jeu éducatif de programmation avec SenseHAT
Programmation réseau avec Python Scapy
[Python] Programmation orientée objet apprise avec Pokemon
Programmation facile Python + OpenCV avec Canopy
[Python] Requête asynchrone avec async / await
Programmation de compétition avec les paramètres de l'environnement local python
Programmation GUI à l'aide de kivy ~ Partie 4 Divers boutons ~
Compréhension complète de la programmation asynchrone Python
Programmation normale avec la programmation Node-RED avec Raspberry Pi 3
Faites de la programmation embarquée avec un développement piloté par les tests avec googletest
Programmation sonore avec Go (super niveau d'introduction)
Ce que vous pouvez faire avec des compétences en programmation