Quant on est sous GNU/Linux, il existe udev, très largement utilisé sur ce système d'exploitation (SE), mais lorsque l'on utilise un système BSD, et en particulier FreeBSD il nous est impossible d'utiliser cette bibliothèque. Cependant les développeurs de FreeBSD ont développé un outil similaire devd(8).
Il est accessible via un socket unix.
J'ai voulu voir comment l'utiliser grâce aux systèmes de notifications du noyau kqueue(2)/kevent(2), avec le langage Python.
Je détaille un peu le script, tout d'abord nous allons initialiser un socket (le programme va fonctionner comme un client).
[...] s_file = os.path.join("/var", "run", "devd.pipe") # Create new socket object s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(s_file) # Return the socket's file descriptor fd = s.fileno() [...]
fd
(file descriptor) est nécessaire pour kevent
.
Les fonctions utilisées par kqueue/kevent sous Python sont accessible via le module select. Nous allons uniquement lire les données qui transitent par /var/run/devd.pipe
.
Ci-dessous l'initialisation du mécanisme de notification.
[...] # Kernel queue object kq = select.kqueue() # Event to monitor (only attach) event = [select.kevent(fd, filter=select.KQ_FILTER_READ, flags=select.KQ_EV_ADD),] # Initialize kevent structure (like EV_SET macro in sys/event.h) ev_set = kq.control(event, 0, 0) [...]
Nous pouvons « boucler » pour afficher les résultats quand un périphérique est branché. Un truc magique avec kqueue/kevent
on a directement accès à la taille du tampon à lire.
[...] for event in events: # Display data from socket (event.data is size to read) print s.recv(event.data) [...]
Voici le résultat lorsqu'une clé USB est branchée.
!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.0 !system=DEVFS subsystem=CDEV type=CREATE cdev=ugen2.2 !system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.1 !system=DEVFS subsystem=CDEV type=CREATE cdev=usb/2.2.2 !system=USB subsystem=DEVICE type=ATTACH ugen=ugen2.2 cdev=ugen2.2 vendor=0x0930 product=0x653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" release =0x0100 mode=host port=6 parent=ugen2.1 !system=USB subsystem=INTERFACE type=ATTACH ugen=ugen2.2 cdev=ugen2.2 vendor=0x0 930 product=0x653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" rele ase=0x0100 mode=host interface=0 endpoints=2 intclass=0x08 intsubclass=0x06 intp rotocol=0x50 +umass0 at bus=1 hubaddr=6 port=2 devaddr=2 interface=0 vendor=0x0930 product=0x 653d devclass=0x00 devsubclass=0x00 sernum="0B4085607142DAD4" release=0x0100 mod e=host intclass=0x08 intsubclass=0x06 intprotocol=0x50 on uhub2 !system=DEVFS subsystem=CDEV type=CREATE cdev=pass2 !system=DEVFS subsystem=CDEV type=CREATE cdev=da0 !system=DEVFS subsystem=CDEV type=CREATE cdev=da0s1
La dernière ligne est intéressante, car c'est le nom de la partition que l'on pourra « monter » sur le système.