Enlace dinamico

Acabo de lanzar la versión 8.0 de FPT_BT4LXMedia. La primera novedad es la nueva versión de Transmission, la 2.21. La segunda es que, por fin, los ejecutables utilizan enlazado dinámico.

Como recordareis, las versiones anteriores utilizaban enlazado estático porque no conseguía que arrancasen desde el disco, a pesar de utilizar LD_LIBRARY_PATH para apuntar al directorio con las nuevas bibliotecas. Para los que no sepan qué es eso, es una variable de entorno que permite añadir nuevas rutas en donde buscar bibliotecas de enlace dinámico, y éstas tienen prioridad sobre las «normales» del sistema. Así, si tengo un programa enlazado con una versión concreta de libc, diferente de la del sistema, puedo instalarla en otro directorio (por ejemplo, /tmp/libs) y lanzar el programa con:

LD_LIBRARY_PATH=/tmp/libs mi_programa

Por desgracia, esto no funcionaba en mi disco duro. Tras investigar mucho, descubrí que el problema estaba en el enlazador dinámico en tiempo de arranque. Resulta que el núcleo sólo es capaz de arrancar, por sí solo, binarios que estén enlazados estáticamente. Para los dinámicos lo que hace es delegar en /lib/ld-linux.so (o /lib/ld-uclibc en la biblioteca uClib). A pesar de llevar extensión .so, este fichero es realmente un programa (enlazado estáticamente, claro) diseñado para cargar en memoria el programa dinámico deseado, analizar qué bibliotecas necesita, cargarlas en memoria si aún no están, realizar toda la operación de enlazado y, finalmente, lanzar el código.

Por desgracia, la versión del enlazador dinámico de la gentoo que utilizo para desarrollar es más reciente que la de mi disco duro, lo que hacía que recibiese un error cada vez que intentaba ejecutar un programa compilado directamente. Para complicar aún más las cosas, la ruta del enlazador dinámico está especificada en cada ejecutable de manera inamovible, estableciéndose dicho valor durante la compilación. Y por si fuera poco, el enlazador de Busybox no permite su ejecución directa, por lo que tampoco podía hacer un simple /lib/ld-uclibc mi_programa.

Ante todo esto, la única solución que me quedó fue la de copiar el enlazador dinámico del entorno de desarrollo en una carpeta diferente y, al compilar bftpd, transmission y ctransmission, especificar la ruta deseada. Esto se hace en la etapa final de enlazado mediante la opción -Wl,–dynamic-linker=path/al/enlazador. De esta manera bastó con copiar el enlazador y el resto de bibliotecas a /tmp/hdd/root/libs y lanzar los programas con

LD_LIBRARY_PATH=/tmp/hdd/root/libs mi_programa

Con esto espero ahorrar algo de memoria. También haré algunas pruebas para ver si los programas funcionan bien con la versión de la uClib del propio disco duro, en cuyo caso podría ahorrar aún más.

FBZX vuelve a la carga

Estos meses estoy trabajando como loco, así que poco tiempo he tenido para corregir cosas. Tengo una cola de mejoras pendientes para Devede que crece día a día, pero hasta que tenga lista la primera versión del nuevo proyecto no me quiero poner con otra cosa.

Pese a todo, he sacado un poco de tiempo para corregir un pequeño bug en el sistema de sonido de FBZX: al utilizar ALSA no definía el tamaño del buffer, sino que asumía que el asignado por defecto era adecuado. Hace unos años funcionaba porque ese valor era de unos 4Kbytes, pero algo han hecho (al menos en Ubuntu) y lo han aumentado mucho, por lo que el emulador iba a trompicones (utiliza el sistema de sonido para ajustar la velocidad). Con OSS o PulseAudio funciona bien, por eso el error pasó desapercibido. La nueva versión 2.4.2 lo corrige.

Entre signos anda el juego

Una de las frases preferidas de mi madre es Está el viejo muriendo, y está aprendiendo; y como en la gran mayoría de los refranes, hay una grandísima verdad oculta en ella.

Y es que estos días estoy peleándome con el micro ARM de un TomTom, y me encontraba con que el código que iba perfectamente en mi PC daba un fallo rarísimo en el GPS: al imprimir el carácter ‘/’ no lo hacía bien; pero sólo ese, el resto los renderizaba perfectamente. Después de mucho depurar, descubrí que el fallo era debido, nada menos, que al signo de una variable. Y es que, a pesar de utilizar el mismo compilador (GCC) para ambos casos, resulta que un char a secas en PC es signed, como todo el mundo asume, pero en ARM es unsigned, por lo que un valor que tenía que ser -1 se convertía en 255 (la segunda parte del problema es que luego operaba con ese valor y con otro de 32 bits, con lo que, al añadirle los 24 bits restantes, no expandía el bit de signo). Una vez añadido el modificador correspondiente, todo pasó a funcionar perfectamente.

Así pues, nunca deis por supuesto el signo de una variable. Consejo de amigo.

Desplazando bits

Hace mucho tiempo, cuando empecé a programar en C, leí una curiosa advertencia sobre los operadores de desplazamiento de bits, los famosos >> y <<. Se afirmaba allí que, al desplazar una variable con ellos, los bits que salían se perdían (lógico, siendo un desplazamiento), pero que los bits que entraban por el lado opuesto tenían un valor indefinido, que podía ser cero o uno según la implementación.

Es cierto que todos los programadores asumen que lo que entra es cero siempre; pero pese a todo, yo, que tiendo a ser demasiado cauto, opté por añadir siempre una máscara AND para poner a cero los bits entrantes y así evitarme sorpresas.

Sin embargo, hace unos días, mientras optimizaba unas rutinas que hacen uso de desplazamientos, decidí investigar más a fondo el tema, porque a fin de cuentas una máscara consume ciclos de reloj, así que si había alguna forma de evitarla siempre sería una mejora. Y lo que descubrí me dejó gratamente sorprendido, porque en realidad el valor de los bits que entran no depende del compilador, sino que está perfectamente definido en el estándar.

Cuando se utiliza el desplazamiento hacia la izquierda (<<), por el lado derecho siempre entran ceros. Ahí nunca hay problemas. Por otro lado, cuando se utiliza el desplazamiento hacia la derecha (>>) en una variable sin signo (por ejemplo, en un unsigned int), por la izquierda también entran siempre ceros.

Sin embargo, cuando utilizamos variables con signo (por ejemplo, short int) en un desplazamiento hacia la derecha, los bits que entren por la izquierda serán una copia del bit de mayor peso del valor original. Así, si teníamos un número negativo (su bit de mayor peso está a uno), al desplazarlo hacia la derecha seguirá siendo negativo, porque los bits entrantes serán unos; en cambio, si era un número positivo (su bit de mayor peso está a cero) los bits entrantes serán cero.

Supongo que la razón de hacerlo así es que, si se utilizan rotaciones para hacer divisiones, se conserva el signo.

Este código ilustra perfectamente lo dicho aquí:

#include <stdio.h>

void desplaza(unsigned int o) {

  signed int s1,s2;
  unsigned int u1,u2;

  s1=s2=u1=u2=o; // asignamos el mismo valor a las cuatro variables

  s1>>=4; // desplazamos cuatro veces cada una de ellas
  s2<<=4;
  u1>>=4;
  u2<<=4;

  printf("Con signo:ntdesplazamiento a la derecha   %08Xn",s1);
  printf("tdesplazamiento a la izquierda %08Xn",s2);
  printf("Sin signo:ntdesplazamiento a la derecha   %08Xn",u1);
  printf("tdesplazamiento a la izquierda %08Xnn",u2);
}

int main() {

  printf("nDesplazamiento de 4 posiciones.n");
  printf("Valor original: 0xA50000A5 (bit de mayor peso a uno).n");
  desplaza(0xA50000A5);
  printf("nValor original: 0x5A00005A (bit de mayor peso a cero).n");
  desplaza(0x5A00005A);

  return 0;
}

La salida es la siguiente, donde se aprecia claramente como el bit superior se replica en los desplazamientos a la derecha de las variables con signo, pero no en el resto de los casos:

Desplazamiento de 4 posiciones.
Valor original: 0xA50000A5 (bit de mayor peso a uno).
Con signo:
  desplazamiento a la derecha   FA50000A
  desplazamiento a la izquierda 50000A50
Sin signo:
  desplazamiento a la derecha   0A50000A
  desplazamiento a la izquierda 50000A50

Valor original: 0x5A00005A (bit de mayor peso a cero).
Con signo:
  desplazamiento a la derecha   05A00005
  desplazamiento a la izquierda A00005A0
Sin signo:
  desplazamiento a la derecha   05A00005
  desplazamiento a la izquierda A00005A0

Mejorando Transmission

Acabo de lanzar una nueva versión de FTP_BT4LXMedia. La gran novedad viene de la mano de CTransmission, un pequeño programa residente que gestiona las descargas, permitiendo limitar el número de ellas que estarán activas simultáneamente.

La razón de añadir este programa es que, debido a las limitaciones de memoria del media center, si se ponen varios ficheros a bajar de manera simultánea éste se satura, y la velocidad de descarga baja a valores ridículos. La solución consiste en bajarlos de uno en uno. Por desgracia, Transmission todavía no permite limitar el número de descargas simultáneas, por lo que he tenido que escribir este programa, que aprovecha las capacidades de control remoto para la tarea. Además, hace el mismo proceso para la subida: los activa de uno en uno hasta que alcanzan un ratio de compartición de 1.0, momento en que vuelve a repetir el ciclo hasta que todos tengan un ratio de 1.5; luego de 2.0, etc. Gracias a él, se pueden añadir todos los torrents que se deseen, y éstos se bajarán de manera ordenada y a la máxima velocidad posible.

Por supuesto, el programa es completamente configurable, y se pueden escoger otros límites mayores si se desea (en el caso del LX Media, lo óptimo es hacerlo de uno en uno, pero en otros equipos la cifra máxima puede ser mayor).

CTransmission es GPL, y se incluye el código fuente en el mismo paquete. Además, puede controlar clientes Transmission de manera remota, simplemente indicando su dirección IP y puerto.

Cumpliendo un sueño

Como muchos ya sabréis, el próximo año se retira definitivamente el transbordador espacial. Eso significa que casi no quedan oportunidades para poder verlo en vivo, por lo que hace una semana me lié la manta a la cabeza y me fui hasta Cabo Cañaveral para poder ver el lanzamiento del Discovery.

El lunes estuve en el centro turístico del Kenedy Space Center, donde tienen un montón de atracciones sobre el espacio. Por ejemplo, tienen varios cohetes de los utilizados en la carrera espacial tripulada: un atlas-mercury, un redstone-mercury, un titan-gemini, y un Saturno IB (el cohete con el que probaban los lanzamientos del Apolo). También tienen una réplica a tamaño natural del transbordador espacial y del tanque y los aceleradores laterales. Estoy harto de verlo en fotos, pero no es hasta que lo ves así, en «real», que te das cuenta del inmenso mamotreto que es. ¡Es gigantesco! Parece imposible que eso pueda planear, mucho menos subir para arriba.

En esta foto se ve el transbordador al fondo (es lo más cerca que nos podíamos acercar). Por desgracia está detrás de la Rotating Service Structure (desde donde se instala la carga útil). Esta parte de la torre se retira horas antes del lanzamiento, cuando ya no admiten turistas, por lo que no es posible sacar mejores fotos (al menos desde donde pude estar).

Yo y el Discovery

En esta otra foto, a la izquierda, está el Vertical Assembly Building, el edificio en donde se montaban los Saturno V y se ensambla el transbordador. A la derecha está la torre de lanzamiento del Ares, la cual, por desgracia, no va a utilizarse ya. Y por último, en primer plano, el crawler, que es el encargado de llevar sobre su lomo al transbordador desde el VAB hasta la zona de lanzamiento.

El plan original era lanzar el Discovery el mismo lunes, pero debido a una fuga en uno de los motores de maniobra orbital se pospuso el lanzamiento hasta el miércoles; volvió a retrasarse hasta el jueves por culpa de un fallo eléctrico en uno de los motores; el jueves hizo un día de perros, lo que obligó a moverlo hasta el viernes; finalmente, una fuga de hidrógeno durante el llenado del tanque principal hizo que se pospusiese toda la operación hasta el 30 de noviembre (e incluso es posible que se retrase hasta febrero del próximo año), con lo que, al final, me quedé sin fuegos artificiales 🙁

Pese a todo, ha sido una experiencia única, y tengo claro que quiero repetir. Y aún quedan dos lanzamientos como mínimo…

Nueva version de Transmission para LX Media

Llevo una temporada sin publicar nada ni actualizar mis programas (sobre todo Devede) porque estoy bastante liado con un proyectillo nuevo, basado en OpenTom (que publicaré, espero, en un mes más o menos). Sin embargo, hace una semana se murió el disco duro de mi LX Media. Tras cambiarlo, decidí aprovechar para intentar mejorar el entorno de desarrollo que tenía para él, y tras mucho esfuerzo conseguí meter una Gentoo autónoma; esto es, ahora dispongo de portage en el disco, con lo que añadir nuevos paquetes es más sencillo. En unos días subiré el sistema completo.

Mientras tanto, ya podéis disfrutar con la nueva versión de FTP_BT4LXMedia, la 6.0, que incorpora la versión 2.10 de Transmission BitTorrent y la 3.0 de bFTPd, además de corregir un detallito de nada en la instalación. Como de costumbre, está en la sección Programas de mi página web.