Detectando memorias USB en Linux: Los servicios HAL y D-BUS

[Visto: 5982 veces]

Recuerdo los tiempos en que para instalar una memoria USB en Linux había que realizar el proceso manualmente. Eso ya cambio hace mucho y de forma automática podemos ver la memoria representada con un ícono en nuestro escritorio, incluso es posible programar aplicaciones que sean notificadas apenas se inserta una memoria USB. El objetivo del presente artículo es revisar los procedimientos que podría utilizar una aplicación en Linux para detectar la presencia de memorias USB haciendo uso de los servicios HAL y D-BUS.En general existen formas de poder detectar automáticamente dispositivos USB en Linux, para ello se hace uso del servicio HAL (Hardware Abstraction Layer) que incorporan las más recientes distribuciones GNU/Linux. HAL, a su vez, puede interactuar con otras aplicaciones desde un demonio llamado hald, para anunciar si se han conectado o desconectado dispositivos entregando todas las características posibles del nuevo dispositivo, algo difícil de lograr si consultamos directamente el kernel o el punto de montaje.

Para que una aplicación pueda conversar con el demonio hald se hace uso de un bus de comunicación llamado D-BUS, el cual es a su vez otro servicio de Linux desarrollado para la comunicación entre aplicaciones o procesos distintos, al estilo de un servicio IPC, con librerías disponibles en C. Adicionalmente a las librerías genéricas de D-BUS (llamadas libdbus), HAL define también sus propias librerías dentro de D-BUS, las cuales definen finalmente un API para poder invocar a HAL desde otras aplicaciones. Estas librerías de HAL se llaman libhal y están escritas en C.

HAL se usa en diversas distribuciones Linux y justamente es el servicio que usan los entornos de escritorio (como Gnome, Xfce y KDE) para la detección de memorias USB, CD, cámaras fotográficas entre otros dispositivos y poder montarlos y mostrarlos en el escritorio automáticamente. Hay otras tecnologías detrás de HAL y D-BUS, como UDEV el cual es el que realmente interactúa inicialmente con el kernel (a través de la carpeta /sys) y luego actualiza HAL con los equipos detectados.

Repasando, la secuencia sería hasta ahora:

KERNEL –> UDEV –> D-BUS –> HAL

En la actualidad HAL es la forma estándar de detectar diversos dispositivos desde aplicaciones en un entorno gráfico. Para comprender mejor el funcionamiento de HAL se sugiere revisar los enlaces al final de la sección.

El servicio HAL incluye diversos comandos de consola en el sistema que interactúan con hald. Los comandos son:

lshal
hal-disable-polling
hal-get-property
hal-set-property
hal-device
hal-find-by-capability
hal-is-caller-locked-out
hal-device-manager
hal-find-by-property
hal-lock

Viendo el código fuente de estos programas se puede aprender el uso de HAL, en particular el más sencillo de comprender es lshal, que realiza un listado de los equipos detectados. Usando el comando “lshal –monitor” se puede ver como el servicio HAL detecta el proceso de conexión de una memoria usb, por ejemplo:

genghis@genix:~$ lshal –monitor

Start monitoring devicelist:
————————————————-
11:34:02.531: usb_device_951_1601_5B7B06A90021 added
11:34:02.635: usb_device_951_1601_5B7B06A90021_if0 added
11:34:02.653: usb_device_951_1601_5B7B06A90021_usbraw added
11:34:08.575: usb_device_951_1601_5B7B06A90021_if0_scsi_host added
11:34:08.575: usb_device_951_1601_5B7B06A90021_if0_scsi_host_scsi_device_lun0 added
11:34:08.587: usb_device_951_1601_5B7B06A90021_if0_scsi_host_scsi_device_lun0_scsi_generic added
11:34:08.645: storage_serial_Kingston_DataTraveler_II__5B7B06A90021_0_0 added
11:34:08.703: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b added
11:34:08.731: volume_part2_size_1024 added
11:34:08.773: volume_uuid_761bf99c_c529_4d5c_bfcd_0e016f245724 added
11:34:08.826: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b property volume.mount_point = ‘/media/disk’
11:34:08.830: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b property volume.is_mounted = true

Y al desconectarla:

genghis@genix:~$ lshal –monitor

Start monitoring devicelist:
————————————————-
12:00:53.971: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b property volume.mount_point = ”
12:00:53.974: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b property volume.is_mounted = false
12:01:05.727: usb_device_951_1601_5B7B06A90021_if0_scsi_host_scsi_device_lun0_scsi_generic removed
12:01:05.728: volume_part2_size_1024 removed
12:01:05.733: volume_uuid_8e2ebe1a_2924_4a0e_8d9b_23cd425f200b removed
12:01:05.735: usb_device_951_1601_5B7B06A90021_if0_scsi_host_scsi_device_lun0 removed
12:01:05.736: usb_device_951_1601_5B7B06A90021_if0_scsi_host removed
12:01:05.747: usb_device_951_1601_5B7B06A90021_usbraw removed
12:01:05.753: usb_device_951_1601_5B7B06A90021_if0 removed
12:01:05.757: usb_device_951_1601_5B7B06A90021 removed
12:01:05.778: volume_uuid_761bf99c_c529_4d5c_bfcd_0e016f245724 removed
12:01:05.785: storage_serial_Kingston_DataTraveler_II__5B7B06A90021_0_0 removed

HAL realiza la detección de dispositivos usando la técnica del sondeo o polling, que produce un consumo de energía. El demonio hald monitorea cada dos segundos (en Ubuntu), mediante el hilo hald-addon-storage, revisando si se ha conectado o desconectado un dispositivo. Por ejemplo, al conectar una memoria usb obtenemos:

genghis@genix:~$ sudo ps auxw | grep hald-addon-storage
107 4734 0.0 0.1 3048 1184 ? S May16 0:03 hald-addon-storage: polling /dev/scd0 (every 2 sec)
107 29507 0.0 0.1 3044 1180 ? S 20:01 0:00 hald-addon-storage: polling /dev/sdb (every 2 sec)

Podemos observar que hald-addon-storage revisa cada 2 segundos el dispositivo /dev/sdb donde tenemos el usb, y también revisa constantemente /dev/scd0 que es el cdrom, a esto se le llama hacer polling.

En particular, leyendo el manual del comando hal-disable-polling (mediante man), se indican los problemas concernientes al uso del polling:

“Unfortunately, polling a storage drive can have adverse side effects if the hardware and/or device driver for the hardware is malfunctioning. Additionally, the operating system kernel itself may offer multiple interfaces for the same device (e.g. /dev/sg0 and /dev/scd0) so even O_EXCL won’t work. Also, polling a drive may decrease throughput in certain (odd and/or broken) configurations; for example, if two IDE drives shares the same host (master/slave), bus traffic and contention caused by polling e.g. the optical drive (slave) can reduce throughput to the hard disk (master) and/or interfere with CD burning on another optical drive (master). Finally, polling a drive incurs an overhead both in the host system (processes get woken up often, preventing the CPU to stay in a deep power saving states) and it may prevent the actual drive from reaching deep power states as well. As a result, more power is consumed and this affects battery life for laptops.”

En la última línea, donde indica “more power is consumed and this affects battery life for laptops”, hace referencia al consumo de energía del método polling y como afecta la duración de baterías en laptops, sin embargo HAL no solamente brinda el servicio de comunicación via hald, también brinda un servicio “Callouts” el cual permite que se invoquen scripts al momento de detectarse un dispositivo, de tal forma que podríamos desactivar el polling (con el comando hal-disable-polling) y solamente esperamos a que se produzca el “Callout” con el cual podríamos definir, por ejemplo, una variable de entorno que permita saber si se ha instalado un dispositivo en particular. Gracias a los archivos de configuración de HAL podemos ejecutar con precisión determinado script según el dispositivo detectado. Ver enlaces de ejemplo al final de la sección.

Alternativamente en lugar de usar el servicio Callout de HAL podemos bajar de nivel y usar el servicio UDEV. Recordemos que UDEV es el servicio que originalmente “alimenta” a HAL con la relación de equipos detectados. UDEV puede invocar un script al insertarse un dispositivo como una memoria USB, y es lo que hace en realidad para alimentar de datos a HAL. En este caso la idea es nuevamente invocar un script que asigne una variable de entorno indicando la conexión de determinado dispositivo, variable que luego pueda ser detectada por una aplicación del sistema.

Finalmente, podemos establecer tres maneras de detectar dispositivos de almacenamiento USB de forma automática desde una aplicación:

1.Esperar que el sistema HAL, junto con hald, monte automáticamente la memoria USB (normalmente lo hace en la ruta /media/etiqueta_del_usb), y luego desde la aplicación hacer constantemente un polling para determinar si se inserto la memoria verificando si existe la carpeta /media/etiqueta_del_usb.
2.Programar con la API libhal. Finalmente es el demonio hald quien termina haciendo el polling.
3.Desactivar hald, que siempre hace polling y consume energía, y hacer uso sólo de UDEV o del Callout de HAL para invocar un script que defina una variable de entorno relacionada con la memoria conectada, variable que debe sondearse vía polling desde la aplicación.

Lecturas recomendadas sobre HAL:

– Detección de Hadware en GNU/Linux con HAL
http://federicosayd.wordpress.com/2007/08/24/linux-y-el-manejo-del-hardware/
http://www.redhat.com/magazine/003jan05/features/hal/

– Relación entre HAL y UDEV
http://linux.sys-con.com/read/139426_1.htm

– Especificaciones libhal y d-bus:
http://people.freedesktop.org/~david/hal-spec/hal-spec.html
http://dbus.freedesktop.org/doc/dbus-tutorial.html

– Ejemplo de programación con HAL:
http://maemo.org/development/documentation/how-tos/4-x/hal_howto.html

– Configuración de Callouts con HAL
http://wideopen.com/magazine/003jan05/features/hal/#callouts
http://eric.ad-sistemas.com/blog/?p=20

– Configuración de UDEV para llamadas a scripts
https://help.ubuntu.com/community/UsbDriveDoSomethingHowto
http://tlug.dnho.net/?q=smeserver_udev_automated_backups

Puntuación: 5.00 / Votos: 6

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *