Cosas mías

March 4, 2008

Cierro el chringuito

Pues eso, que estoy algo cansado de forzarme a escribir una entrada válida para poner aquí (y no es que las que pongo sean de mucha calidad), así que de momento voy a dejar estar un poco el tema.

No es un cierre absoluto, sino más bien cautelar, ya que iré haciendo eco de mis entradas en Geeks y quizás ponga alguna otra cosa, pero no con la frecuencia habitual…

Pues eso, que hasta luego.

March 3, 2008

Singleton con y sin Singleton

Filed under: Programación

Ahora que están de moda los antipatrones, voy a explicar un patrón que es muy famoso pero que no me gusta absolutamente nada, no por el diseño del mismo, sino por los efectos laterales no deseados que genera. Por ello también voy a explicar otra forma de construirlo que me gusta más, aunque adolece de otras limitaciones.

Singleton es un patrón que nos obliga a tener una sola instancia de una clase, es decir, globalmente sólo podremos disponer de un objeto de ese tipo. El truco está en conseguir que, hagamos lo que hagamos, no podamos crear más de una instancia.

En lenguajes como C++ este patrón tiene menos utilidad que en C++/CLI, C# o VB.NET, ya que la forma clásica de hacer algo similar es tener una variable global accesible por todos los módulos, cosa de la que suele encargarse el enlazador de hacer.

Pero los lenguajes .NET adolecen de falta de variables globales; es decir, no puedes tener un objeto global y visible en toda la aplicación. Personalmente no entiendo este purismo tan quisquilloso, ya que los lenguajes .NET no son precisamente orientados a objetos puros, y menos aún con la especificación 3.0 de C#. Y si encima este hecho complica bastante ciertos desarrollos, el absurdo sube de nivel.

Pero es lo que hay.

La solución para tener un objeto global es disponer de una clase estática. Si bien a priori resulta una buena idea, en la práctica no lo es tanto. Independientemente del hecho de que los constructores estáticos en .NET no funcionan muy bien o, en otras palabras, tienen bastante bugs (al menos en la versión 2.0, aunque dudo mucho que lo hayan solucionado en los SP1), tenemos ciertas limitaciones, como la imposibilidad de que se llame a otro constructor estático de forma encadenada…

¿Y por qué comento esto? Pues porque el patrón Singleton utiliza una variable y un constructor estático. Veámoslo en C#:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4:  
   5: class Singleton
   6: {
   7:     public static Singleton Instancia=new Singleton();
   8:  
   9:     private Singleton() {}
  10:  
  11:     public int Numero;
  12:     public void DiNumero()
  13:     {
  14:         Console.WriteLine(Numero++.ToString());
  15:     }
  16: }
  17:  
  18: class Program
  19: {
  20:     static void Main(string[] args)
  21:     {
  22:         Singleton.Instancia.Numero = 33;
  23:         for (int i = 0; i < 10;i++)
  24:             Singleton.Instancia.DiNumero();
  25:     }
  26: }

Observamos que el truco está en definir un constructor privado. Al hacerlo, ya no podremos equivocarnos y crear varias instancias de esta clase, y la única forma de acceder al único objeto que pueda haber en toda la aplicación es mediante

   1: Singleton.Instancia

Si intentamos crearnos un objeto del tipo Singleton, el compilador protestará y nos dirá que el constructor no está accesible.

Si alguien quiere una explicación más en detalle, se puede pasar por la MSDN o por aquí.

¿Nadie ve el problema?

Pues hay dos. El primero ya lo hemos dicho: tenemos un objeto global al sistema, que es estático y por tanto sigue unas reglas algo diferentes, como la imposibilidad de hacer una llamada a otra variable estática que implemente su propio constructor estático dentro del constructor de nuestro Singleton… O en otras palabras: no podemos tener Singletones anidados, no al menos bajo .NET.

Pero el mayor problema es otro. Cuando se habla de Singleton, se pone un ejemplo con dos líneas de código y listo. Pero una clase de la Vida Real™ no es sencilla. Tendremos varios métodos miembro, así como variables. ¿Cómo las inicializamos? ¿En el constructor? ¡Pero si no tiene constructor al que podamos pasarle valores! ¿Las ponemos públicas? ¿Propiedades?

Una solución es la mostrada aquí:

   1: Singleton.Instancia.Numero = 33;
   2: for (int i = 0; i < 10;i++)
   3:     Singleton.Instancia.DiNumero();

Pero a mí al menos eso me parece una guarrería mayor, y más cuando haya varios datos miembro, como suele ser habitual en clases no triviales… La única cosa que podemos hacer es especificar valores por defecto en el constructor estático:

   1: private Singleton() { Numero = 50; }

Pero eso sólo alivia el problema, no lo soluciona.

Qué bonito sería que pudiéramos indicar algo como

   1: [Pattern(Singleton)]
   2: class Singleton
   3: {…

Y disponer de la clase como si tal cosa… Pero esa es otra guerra.

Otra aproximación

Veamos ahora una variante, que es la que yo implemento en mis propios programas. Primero el código:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4:  
   5: class MiSingleton
   6: {
   7:     private static int m_cuenta=0;
   8:  
   9:     private int m_numero;
  10:     public MiSingleton(int num)
  11:     {
  12:         m_cuenta++;
  13:         if (m_cuenta > 1)
  14:             throw new Exception("RFOG Singleton Exception");
  15:  
  16:         m_numero = num; 
  17:     }
  18:     public void DiNumero()
  19:     {
  20:         Console.WriteLine(m_numero++.ToString());
  21:     }
  22: }
  23: class Program
  24: {
  25:     static void Main(string[] args)
  26:     {
  27:         MiSingleton m = new MiSingleton(33);
  28:         for (int i = 0; i < 10;i++)
  29:             m.DiNumero();
  30:  
  31:         MiSingleton n=new MiSingleton(88);
  32:     }
  33: }

Aquí encontramos otros problemas y otras limitaciones, pero personalmente me gusta más así. Definimos una variable estática, un entero que nos servirá para contar cuántas instancias de esta clase tenemos.

Definimos un constructor público al que podremos pasarle cualquier número de parámetros que queramos, de hecho se trata de una clase normal y corriente que tiene un bloque de código concreto en el constructor:

   1: m_cuenta++;
   2: if (m_cuenta > 1)
   3:     throw new Exception("RFOG Singleton Exception");

La segunda vez que intentemos instanciar esta clase obtendremos una excepción. Aquí la limitación está en que nos daremos cuenta de nuestro error en tiempo de ejecución, no de compilación, lo que ciertamente es una desventaja seria pero que pierde fuerza cuando nos enfrentamos a las limitaciones y bugs de los constructores estáticos.

La segunda instanciación dentro del bloque de main() lanzará la excepción. La otra limitación a esto viene de la imposibilidad de tener variables globales y de que tengamos que pasar m siempre que queramos usarlo.

Lo ideal sería tener ambas opciones juntas, pero ciertamente dentro de .NET es imposible.

March 1, 2008

El loco de la colina y las colinas locas (Sobre el SP1 del Vista)

Ya sé que últimamente no abundan los contenidos técnicos por aquí, pero estoy laboralmente muy ocupado y el tiempo libre que tengo lo paso leyendo y relajándome, imagino que de aquí a un mes volveré a estar más libre… Eso o estaré en paro, ya que no me gusta absolutamente nada la dinámica que está tomando mi curro, con salidas a toda España a reparar máquinas de las que no entiendo ni quiero entender y que ya de por sí su comprensión suponen un oficio en sí mismo.

Pero hoy no voy a hablar de mí, sino de Microsoft y sus últimas pifias. Ahora como MVP tengo línea directa, pero a fin de cuentas es como si no la tuviera, ya que por lo menos a mi no me hacen ni p*to caso. Y a veces son cosas muy serias, como las del final de esta entrada.

Visual Studio 2008
Quien tenga una subscripción a la MSDN lo habrá podido descargar más o menos desde noviembre del año pasado, así que debe estar bastante familiarizado con él. En mi caso no le encuentro ninguna pega destacable. Aunque tampoco es que le haya dado mucha caña: una pequeña aplicación en C#, dos tonterías en MFC y sí una espuerta de DLLs en Win32. Y si fallara haciendo DLLs pues ya sería la rehostia…

Estooooo… ¿Digo que no falla? Pues sí que falla, o mejor dicho fallaba. Y no sé cómo lo han actualizado, pero lo han hecho. Si uno crea un proyecto con una DLL nativa, y usa esa DLL nativa en otro proyecto dentro de la misma solución, el linker revienta a la hora de enlazar. Es muy curioso, porque solo revienta justo después de reiniciar Windows, y sólo en Vista. O en otras palabras: la primera compilación parcial tras un reinicio hace que el linker genere un error interno. Curioso, ¿no?

Pues tras informar del error (yo fui el primero, luego comenzó a pasarle a más gente), lo han solucionado. ¿Cómo? Pues no lo sé. El Visual Studio no lo han actualizado, así que ha debido ser una actualización secreta de esas que no te dicen nada o junto a alguna actualización del propio Windows.

Decir que está actualizado es mucho afirmar, más bien el problema queda minimizado y sólo ocurre con muy poca frecuencia, tan poca que apenas es molesto.

Más Visual Studio 2008 y el SDK 6.1
Otra, esta algo más grande. Hay dos nuevos Windows SDK, ambos con la versión 6.1. Uno para Vista SP1 y otro para Windows Server 2008. El que trae el Visual Studio es la versión 6.0A.

¿Los ha instalado alguien? ¿En Vista x64, con o sin SP1? No hace falta que lo hagáis, ya que si bien se instalan perfectamente, cuando utilizamos el nuevo “Windows SDK Configuration Tool” para cambiarle al VS2008 el SDK activo, lo rompe y lo deja incapaz de compilar; en el caso del SDK de Vista, ya no es posible crear aplicaciones en C++/CLI, y en el caso del de Windows Server, nativas. Tras comprobar que la instalación del SDK del Server falló, y un par de cuelgues duros de Vista durante la reinstalación, al final el problema que presenta el SDK del Server es el mismo que el del Vista.

Tampoco vale la pena que utilices dicha herramienta para volver al status anterior: El Visual Studio 2008 ya no te volverá a funcionar a no ser que desinstales los SDK (menos mal).

¿Solución? Ninguna. Silencio administrativo.

Windows Vista SP1
Antes de la salida pública del SP1 los suscriptores a la MSDN también tienen acceso a dicho Service Pack. Ciertamente pagar una suscripción a la MSDN cada vez tiene menos sentido, sobre todo las caras, ya que MS va liberando poco a poco casi todo lo que antes costaba dinero o tenías que ser un Partner para obtenerlo. Como consecuencia de ello, los subscriptores pusieron el grito en el cielo y al poco se permitió la descarga del SP1. Decir que tampoco a los MVP que no fueran betatester del propio SP1 nos dieron acceso a él…

Pues bien, tras estar un par de semanas con él instalado de forma limpia, es decir, instalas el Vista, luego el SP1 y sigues con todo lo demás, ya que los chicos de las altas esferas han decidido que no se pueda crear un CD integrado, mis conclusiones no podrían ser más pésimas. Vamos allá.

Windows Mail. Si antes del SP1 era pésimo, después de él sigue siéndolo. Es decir, los parpadeos continúan, los autismos también, y en general los problemas de que adolece se siguen presentando de igual forma, aunque con un, digamos, 10% menos de frecuencia.

Arranque y apagado. Ninguna mejora. Tarda la misma eternidad en arrancar y parar, y durante el arranque sigues dejando de tener todo funcional hasta pasado un buen rato después del que te muestre el escritorio.

Autismos varios. Es decir, esas congelaciones que se producen en ciertas aplicaciones se vienen produciendo con algo menos de frecuencia, pero siguen pasando.

Otros. Parece ser que sí que han mejorado algo la I/O por prioridades, y ahora copia y mueve archivos mucho más rápido, pero siguen los autismos en cuanto a arrastrar y soltar. El IE se sigue cayendo solo igual que antes, el explorador sigue sin recordar posiciones ni ciertas configuraciones y en general, salvo la copia, la gestión de archivos sigue siendo tan mala que antes, lo que me lleva al siguiente punto.

No se copian ni mueven todos los ficheros
Pues lo dicho. Así que ojito con copiar y luego borrar el original sin comprobar la copia. Me da igual que se deba a los hooks de terceros o a lo que sea. Es completamente inaceptable. Ni siquiera Linux en sus peores días hacía eso.

Antes del SP1 experimenté el problema de dos formas distintas. En la primera, al mover ficheros, en el origen quedaban restos que si bien se habían copiado, no se habían borrado. En la segunda, al borrar ficheros, me pasaba lo mismo, pues supuse que se debía a que alguien bloqueaba el fichero y se olvidaba de liberarlo, ya que la única forma de poderlos borrar era saliendo y volviendo a entrar en la sesión. Como eran ficheros que no se habían visto en ningún momento, el candidato que generaba el problema debía ser el propio Vista.

Después de eso otro MVP comentó que le parecía que le había fallado la copia, pero no estaba seguro de ello.

Y yo me quedé con la mosca detrás de la oreja… Después instalé el SP1, y observé el problema que cuento en la sección siguiente (que ya es el súmmum de todo), por lo que procedí a limpiar la unidad…

¿Imaginan? Pues se quedaron ficheros sin mover. Bien es cierto que eran ficheros ocultos y de sólo lectura, pero otros ocultos y de sólo lectura se movieron, así que ese no era el motivo. Un arrastrar y soltar los copió, pero el problema está ahí.

Y vayamos al apoteósico final.

Particiones sucia
Tengo una partición con la que trabajo todos los días, donde está el código fuente de la empresa, almacenes de correo y demás. El System Restore está deshabilitado globalmente. La unidad es NTFS formateada desde la misma instalación. Pues bien, de 11 GB de datos que hay (datos en disco, teniendo en cuenta el tamaño del cluster), en el disco hay realmente más de 20 GB. Tras borrar todo lo del disco, me seguían quedando esos 10 GB ocupados, o sea, que son basuras que deja el Vista, ya que a nivel de usuario no queda nada. Activando mostrar ficheros ocultos por el sistema operativo, tomo posesión de "System Volume Information" y veo un montón de archivos con nombres de GUIID con tamaños de entre varios cientos de megas y gigas… Y de repente, antes de que me dé tiempo de mirarlos, ¡desaparecen! y la unidad se queda como debería haber estado en un primer momento.

¿Qué se oculta ahí? ¿Por qué desaparecen esos ficheros nada más verlos? ¿Qué son esos restos (el system restore no puede ser ya que está desactivado) que Vista no quiere que tengamos acceso a ellos?

Me hubiera gustado haber recibido una respuesta oficial, creíble y documentada. Pero no fue así. Silencio administrativo.

¿Por qué roba Vista ese espacio en disco?

Podría ser un resto del shadow copy de la copia de seguridad del propio Vista: en ese caso, chapuzas dobles y triples. Nunca los programas de copia de seguridad que han acompañado al sistema operativo han sido buenos, pero llegar hasta ese punto… Es decir, tengo programado el Backup del Vista para que haga copia de esa unidad sobre otra, si son los restos de la preparación del shadow, lo dicho.

Podría ser que aunque se ha desactivado globalmente el System Restore, Vista pasara olímpicamente de nosotros e hiciera copias… en una unidad que nunca lo ha tenido activado. Aquí entraríamos en cuestiones de otro tipo, como las actualizaciones ocultas que se instalan de forma oculta aunque las tengas desactivadas… lo que me parece un punto de soberbia, prepotencia y abuso de poder completamente intolerable…

No se me ocurren otras posibles causas, y las que se me ocurren mejor no mencionarlas (qué casualidad que sólo pase en la única partición en la que hay código fuente…) etc.

El tema es que han pasado unos días y ya tengo otra vez la partición con 5 gigas de basura… Pero esta vez no se me escapan…

Eso será después de que instale XP.

February 8, 2008

Hemos leído: Serial Port Complete 2nd. Ed. (Jan Axelson)

Filed under: Programación, Lecturas

Otro que ha caído como una pera madura de un árbol. Y no es porque no traiga información, que la trae, y mucha, sino porque… porque… aparte de los elementos de diseño hardware, que no me interesan lo más mínimo –para eso están los chatarrillas, como yo los llamo[1]-, no me aportan nada nuevo, sino más bien… se queda muy corto.

Pero veamos qué trae el libro. Los primeros capítulos son un poco rollo, con una serie de explicaciones teóricas sobre nomenclaturas, características y opciones. Los siguientes sí que les pueden resultar interesantes a los diseñadores de hardware, ya que incluso modela ecuaciones mediante código. Habla de largos máximos, de atenuaciones, masas, etc., todo ello cuestiones de diseño que no me incumben y de las que sé lo justo para poder lidiar con los problemas habituales cuando se programa con puertos serie de por medio. Sigue con más explicaciones teóricas sobre los puertos serie de los PC.

Luego trae dos capítulos enormemente interesantes ya que la literatura sobre el tema es bien escasa: RS-485, que es un RS-232 en el que se usan dos hilos diferenciales como soporte físico para el envío y recepción de datos, lo que tiene la ventaja de que al ser una señal diferencial tiene muchas menos pérdidas y en consecuencia permite cables de mayor longitud, y la desventaja de que no se permite enviar y recibir simultáneamente ya que ambos hilos se usan a la vez para la comunicación. Eso no quiere decir que no pueda ser bidireccional, sino que o bien se envía o bien se recibe. Personalmente he usado ampliamente este soporte físico para realizar comunicaciones dentro de una máquina, y lo cierto es que no tengo claro si las ventajas superan a los inconvenientes o al revés. En fin, con estos dos capítulos cualquiera se vería cualificado para diseñar sobre este formato de hardware.

Quiero hacer notar (y esto no viene en el libro), que existen protocolos más modernos y robustos basados en los hilos diferenciales, como el CAN, que usa la Mercedes dentro de sus coches. La ventaja es que resulta enormemente seguro en cuanto a pérdida de datos y que muchos temas de protocolos –como el de lucha para conseguir el control del bus- se llevan a cabo a nivel de hardware, con lo que liberan al programador de tareas bastante complejas y que llevan mucho tiempo desarrollar.

El capítulo 8 desvaría un poco, y seguro está puesto para llenar páginas: habla del Bluetooth, Wifi, etc. como protocolos serie… El primero de ellos lo es, pero el segundo seguro que no.

Dos capítulos dos sobre desarrollo con puertos serie bajo .NET (y a C++ y VB que los zurzan). Nada nuevo bajo el sol y que no esté contemplado más o menos bien leyendo la documentación de la MSDN. Aparte de algún gazapillo perdonable (un System.String se envía en formato UNICODE, no ASCII, sólo por poner un ejemplo, ya que hay alguno más), el texto trae los típicos ejemplos realizados en VB.NET y C#, facilones y evidentes. En el segundo profundiza algo más, explicando los eventos y cómo realizar programación asíncrona, aunque sólo toca la superficie.

Y es que lo que trae es apenas nada en cuanto a desarrollo de software en el que intervenga una o más UARTS, os lo digo yo que llevo buena mili con el tema.

Luego viene un capítulo sobre puertos serie sobre dispositivos, explicando un modelo de Microchip que incorpora una UART, tratando sobre cuestiones de diseño y de programación en C sobre dicho micro. Ciertamente es un capítulo loable, pero dado que cada microprocesador incorpora las UART y sus registros a su manera, tan sólo sirve para dar una ligera idea de lo que uno se puede encontrar cuando programa un procesador.

Y digo flojito porque una obra que se precie de completa debería haber contemplado este tema con mayor profundidad. Debería haber explicado cómo funcionan las UART dentro de un microprocesador grande, con toda la parafernalia de los niveles de interrupción, vectores instalables y prioridades de la UART frente a los timers (por poner un ejemplo). También debería haber cubierto en profundidad los chips UART, pastillas que llevan 4, 8 ó 16 UARTS y que se anexan al bus de datos (y cómo integrarlas dentro del firmware), o cómo montar cores UART dentro de una FPGA o similar…

Sí que trae un capítulo interesante pero de nuevo flojito sobre diseño de protocolos sobre canales serie. De nuevo apenas contempla lo más básico.

Finaliza con mucho rollo sobre convertidores USB-RS232, muchos de los temas apenas son interesantes porque de eso ya se ocupa el fabricante del chip, pero hay que llenar páginas poniendo rollos en lugar de escribir sobre lo que hay que escribir.

El libro no está mal, pero apenas cubre una iniciación tanto en el diseño del hardware como en el desarrollo con estos dispositivos; es perfectamente válido para cualquiera que empiece con el tema, pero desde luego no llega a los talones de cualquier aplicación o diseño de la Vida Real™.


[1] Que nadie se tome a mal el nombre. Dentro de lo que yo llamo nomenclatura simpática, un diseñador de hardware en un chatarrillas, un diseñador gráfico un pintamonas, y un jodío developer un chafateclas, y desde luego no hay ninguna intención peyorativa, sino que simplemente me resultan nombres tan irreverentes como yo mismo soy.

Hemos leído: USB Complete. Third Edition (Jan Axelson)

Filed under: Programación, Lecturas

Esta lectura, más que por devoción, ha sido por obligación, aunque cuando compré el libro lo hice por devoción. Es decir, mi idea era leer algo serio sobre USB para ver cómo funcionaba, y trastear un poco para poder añadir esa especialización a mi currículum… Pero tras haberlo leído mejor no pongo nada, que ya tengo suficientes quebraderos de cabeza.

He dicho que la lectura ha sido por obligación, y es cierto. Hace dos semanas me pidieron que evaluara hacer un driver USB para una placa que estamos haciendo, o más bien que estoy haciendo, pues estoy más o menos a cargo del tema completo, como si hubiera vuelto a mis orígenes… Recuerdo el cambio de color de cara del ingeniero cuando le comenté que tenía que hacer una placa conectada por USB (lo que, ahora que conozco el percal, entiendo perfectamente, ya que el chaval no es ningún gallina en cuanto al diseño de hardware se trata). Comenzamos a planificar el tema, y mientras él buscaba y evaluaba microprocesadores, chips necesarios y todo eso, yo leía afanosamente este libraco (encima estaba sin ordenador, con mi anterior placa base en el cielo –o infierno, vaya usted a saber- de las placas base, y esperando lo que ahora disfruto). Nos cruzamos una buena cantidad de llamadas, vamos lo típico, que si esto vale esto, que si necesito xx MPIS, que si puedo usar BGA, que cambia esto del protocolo de comunicaciones porque no voy a poder atenderte… Hasta que acabé de leer el libro. Entonces hice La Llamada.

YO: ¿Querías un USB puro?

JEFE: Sipi.

YO: 6 meses + fase beta + fase de pruebas sólo para el driver…

JEFE: ¿A cualo?

YO: Lo que oyes.

JEFE: ¿No se puede acortar?

YO: No creo… -Pensando que en un par de meses podría estar, pero porsiaca…

JEFE: Pos vaya…

YO: Peeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeero…

JEFE: ¿Sí? – Con tono esperanzado

YO: Podemos usar esta solución. Cada chip lleva número de serie, el driver te lo da el fabricante, acortamos también el desarrollo de nuestro hardware porque la solución nos da un acceso directo a una UART, hay dos fabricantes, si uno falla tenemos al otro aunque cambiarlo requiere cambios en el hardware…

JEFE: Pos fale…

Y luego hice la otra llamada: -Gallinica, que vamos a usar lo que has propuesto. Vuelta del color a su cara, y todos tan contentos.

Bueno, después de la anécdota, vamos al libro.

No está mal, aunque no es lo que esperaba (más bien el USB no es lo que esperaba, pero bueno). Comienza explicándonos qué es el USB, su velocidad y lo compara con otros protocolos serie, describiendo también los cuatro modos y las cuatro velocidades junto a qué soporta cada clase…

Luego entra de lleno a explicar cómo funciona el protocolo en sí, cómo se forman los comandos y su contenido, de qué tenemos que preocuparnos y de qué no (por ejemplo, todo el tema de códigos de control, CRCs y demás lo hacen los chips directamente).

Y aquí es donde me entró el canguelo… En mi vida laboral he diseñado varios protocolos que han ido por encima de hilos RS232, RS485, Paralelo (no necesariamente de 8 bits), sockets, incluso pines sueltos de un microprocesador, pero nunca he visto algo tan barroco ni tan enrevesado. Es increíble la complicación del protocolo, tan increíble que pienso mal de él. Que si transaction que si token packet, que si pid, que si endpoint, que si data, que si frames, que si latencias… Y luego están los cuatro modos. Y no hablemos de la negociación e identificación cuando se enchufa un dispositivo USB con las quince espuertas de mensajes que se tienen que enviar, y más aún cuando arrancan y soportan ahorro de energía y cosas así. Ahora entiendo por qué hay tanto driver mierdoso… Lo que es mierdoso no es el driver, sino el protocolo.

Digo que pienso mal porque un protocolo diseñado con esta mala leche sólo puede tener alguna de estas explicaciones: O bien los que lo hicieron cobraban por tiempo de discusión, o por complejidad o quisieron cerrarlo tanto que sólo unos pocos fueran capaces de entender y desarrollar el protocolo…

Continuando con el libro, el autor nos cuenta cómo funciona cada modo y las APIs que hay para hacerlo funcionar. También comenta –por encima- cómo hacer un driver. Y da algunos ejemplos sin mucha utilidad para trastear desde Visual Basic y C++. El libro está centrado en explicar el funcionamiento de la clase HID (Human Interface Device), quizás la más común de todas las clases de dispositivos USB aunque también entra en las demás.

El libro termina con las especificaciones eléctricas y con un capítulo sobre algo llamado USB-on-the-GO, que no he leído y que tampoco sé qué es ni me interesa saberlo.

Hemos leído: Multithreading Applications in Win32 (Beveridge y Wiener)

Filed under: Programación, Lecturas

Este libro ha sido una completa decepción ya que sin ser malo –que lo es-, no me ha aportado nada nuevo. Yo esperaba descubrir esplendorosas técnicas más allá de lo habitual… pero o no las hay o los autores no se enteran mucho.

El libro ha envejecido bastante bien, ya que si obviamos los comentarios sobre Windows 3.x, 95 y NT, casi todo lo explicado continua siendo actual y útil… bugs incluídos. Eso no es óbice para que los ejemplos sean pésimos y empleen código bastante malo y desactualizado. Si bien lo último es lógico, lo primero no. Las carencias del código llevan hasta a no liberar objetos del núcleo y del GDI en algunos ejemplos… algo inaceptable dentro del código moderno (y menos aún del anterior, ese olvido terminará degradando Windows 95 hasta que nos fuerce el reinicio).

Los autores presentan una descripción somera sobre multitarea, y luego pasa a contarnos cómo usar un hilo mediante CreateThread() y cómo esperar a que éste acabe de forma incorrecta –ellos mismos lo dicen-. Tras eso nos cuentan cómo utilizar las funciones Wait… (WaitForSingleObject, WaitForMultipleObjects, …) para recibir el evento de finalización.

Luego viene un capítulo clásico que explica las secciones críticas, los mutexes, los semáforos y los eventos (éstos últimos explicados de forma bastante oscura y barroca), sin aportar nada nuevo y enfocados al tema práctico, explicando con qué funciones de Win32 se pueden hacer.

También nos cuenta cómo suspender y activar los hilos, y cómo cambiar su prioridad.

Un tema bastante interesante, pero visto casi de pasada, es la entrada/salida asíncrona. Es decir, la I/O overlapped, las APC y los completion ports. La Overlapped I/O funciona ordenando una lectura/escritura y esperando el evento correspondiente de que se ha producido (así es cómo funciona la E/S dentro del .NET y por eso un programa en C# que lea y escriba frecuentemente se ejecuta incluso más rápido que un programa hecho en C++ siempre que no use esas técnicas, que suele ser lo habitual). Las APC son algo más o menos igual, pero los completion ports son una cucada (y es una de las cosas que había leído que existían pero que no había mirado todavía); Creas un pool de hilos, los asignas mediante unas funciones y e voilà, el sistema se encarga de ir despertando/durmiendo los hilos conforme vayan haciendo falta. Todo un hándicap para la programación de servidores.

Y luego entramos en la segunda parte, los temas avanzados, como el uso de volatile y el concepto de transacción. Continúa un nuevo capítulo sobre el uso de hilos con la CRT, o más bien qué cosas hay que tener en cuenta cuando se usan hilos que llaman a funciones de C estándar.

Otro más sobre C++ y cómo C++ facilita la eliminación de errores potenciales gracias a los constructores/destructores, así como la técnica para que las funciones miembro de una clase puedan ser usadas como funciones de hilo…

Sigue con los hilos bajo MFC, la separación entre hilos con bucle de mensajes e hilos sin él, y las cosas que hay que tener en cuenta cuando un hilo maneja o accede a ventanas…

El GDI y las cosas a tener en cuenta cuando se trabaja con elementos del mismo, que no son seguros en cuanto a hilos y la demostración de que la peor técnica para controlar ventanas MDI es usar un hilo para cada ventana.

El siguiente es un poco risible. Cómo depurar programas que usen hilos; en fin, aparte de lo habitual, el autor recomienda determinación, paciencia y creatividad.

Los dos siguientes, pese a ser poco profundos, resultan interesantes: DLL e hilos dentro de ellas y comunicación entre procesos: ficheros mapeados en memoria, pipes, memoria compartida, mailslots, DDE, OLE… El problema es que cuando podría profundizar, toca todos estos temas de refilón. En fin.

El libro termina desvariando un poco, con un capítulo sobre diseño de aplicaciones, ISAPI y poco más.

Ciertamente es una obra demasiado sencilla dado lo complejo del tema y pese a ser tan monotemática…

December 25, 2007

Hemos leído: Reversing. Secrets of Reverse Engineering (Eldad Eilam, Wiley)

Sí, ya sé, muchos libros técnicos estoy leyendo últimamente, pero es que voy por rachas, y ciertamente este lo he disfrutado casi como una novela. El título es correcto: Ingeniería inversa con pelos y señales. Toda una gozada pese a lo denso del contenido, aunque el que esto suscribe en su juventud tuvo cierta etapa sobre la que es mejor correr un estúpido velo, y casi nada de lo tratado aquí le ha sonado a nuevo.

Tras una larga introducción de más de 130 páginas, justificativa de la ingeniería inversa, y en la que se explica muy por encima todo lo que se debe saber antes de sentarse a realizar una sesión de este tipo, incluyendo qué herramientas usar y cómo funcionan, el autor entra de lleno en materia.

El capítulo 5, primero de la segunda parte, incluye una lección magistral (de magnífica, no de magisterio) en la que se realiza ingeniería inversa sobre un subconjunto del API incluido en NTDLL.DLL, perteneciente a las tripas de Windows. En concreto indaga en las funciones del grupo RtlGenericTable, y nos va demostrando paso a paso cómo, en un alarde de inteligencia y buen hacer, qué hacen dichas funciones y cómo. Llega hasta a reconstruir la estructura de datos no trivial que usan dichas funciones: una variante optimizada de los árboles-B que coloca los nodos más visitados encima del todo. Lo dicho: todo un alarde de inteligencia, deducción y aplicación de la ingeniería inversa. El lector realmente ve lo que el autor está haciendo y no le quedan dudas sobre el funcionamiento de dichas funciones.

El siguiente capítulo tampoco se queda chiquito. Se nos demuestra paso a paso cómo obtener la estructura de un fichero… que guarda ficheros encriptados con encriptación fuerte. Ahí es nada. Partiendo de la picardía, de la inspección del código ejecutable del programa que crea el fichero y el visionado hexadecimal del propio fichero, nos va reconstruyendo paso a paso todo el proceso, llegando a obtener la información suficiente para poder realizar un nuevo programa que podría usar dicho formato de fichero. Evidentemente, no rompe el algoritmo de encriptación, pero sí lo identifica y llega a mimetizar el comportamiento del programa original… y eso que el fichero en sí también está encriptado. No me canso de repetirlo: una verdadera gozada de inteligencia y deducción aplicada.

El siguiente es algo más flojito, aunque desde luego suficiente. Nos explica cómo se puede auditar un ejecutable para detectar problemas potenciales de seguridad (como, por ejemplo, sobreescrituras de buffer), y en el octavo vuelve a dejarnos con la boca abierta: tras explicarnos por encima los tipos de malware más comunes, destripa el Backdoor.Hackarmy.D, obteniendo incluso la lista de comandos remotos que acepta, así como la vía de infección e instalación.

En el 9 nos cuenta las técnicas de protección anti copia y anti pirateo y nos explica las vías de entrada para saltárnoslas, pero sin profundizar mucho. También afirma algo que muchos fabricantes de software no se enteran o no quieren enterarse: que no existe ninguna protección por software (aunque se apoye parcialmente en hardware) que no pueda ser reventada tarde o temprano.

El capítulo 10 cubre las técnicas existentes para evitar la ingeniería inversa y vuelve a darnos las pautas para eliminarlas, y en el 11 nos vuelve a dejar, de nuevo, perplejos, saltándose varias protecciones avanzadas de forma sencilla y eficiente mediante el uso de un programa de ejemplo. También nos cuenta que hay un sitio en internet dedicado a este tipo de técnicas tomadas como juego, es decir, que alguien propone programas de ejemplo para que otros los rompan. La web es http://www.crackmes.de.

La cuarta parte tiene dos capítulos. En el primero nos cuenta cosas sobre el .NET y cómo invertir las ofuscaciones y demás protecciones, sin profundizar mucho (ya que ciertamente la mayoría de este tipo de tareas son poco menos que triviales dentro del .NET), y en el siguiente nos cuenta el estado del arte (en 2005) de las técnicas de descompilación, es decir, de las técnicas existentes para convertir un programa ejecutable en un código fuente equivalente en algún lenguaje de alto nivel, en general C. Estando de acuerdo con el autor y con otros muchos estudiosos del tema, en el proceso de compilación existe cierto grado de pérdida de información que es irreversible, sobre todo con compiladores optimizadores agresivos.

El libro termina con varios apéndices que explican cómo detectar estructuras de datos, prólogos y epílogos de las llamadas de función, y la traducción de ciertas secuencias binarias a un código fuente equivalente.

Como ya he dicho, y pese a lo arduo de la lectura, el libro es toda una gozada si eres de esas personas inquietas a las que les gusta emplear la deducción y la inteligencia a tareas aparentemente imposibles de realizar… para descubrir que un poco de picardía, de intelecto y de conocimientos son suficientes para asombrarse incluso de uno mismo.

December 16, 2007

Hemos leído: C++/CLI in Action (Nishant Sivakumar, Manning)

Filed under: Programación, Lecturas

Esto sí que es un libro técnico, y lo demás son tonterías. En otras palabras: el libro es bueno, muy bueno, de lo mejorcito que he leído de cualquier tema técnico relacionado con la programación.

Como el título indica, se trata de una obra eminentemente práctica y profunda que trata la mayoría de los aspectos del C++/CLI sin entrar para nada en detalles sobre el .NET excepto al final, cuando explica algo sobre WPF y tecnologías asociadas.

El libro parte de que al menos sabes C++ a nivel de programador profesional, y si tus conocimientos incluyen algo de C++/CLI, mejor que mejor. Dividido en tres partes de tres, dos y tres capítulos respectivamente, lo más interesantes a mi modo de ver son las dos primeras partes.

Tras una introducción a C++/CLI explicando todos los aspectos básicos, como la declaración y la sintaxis del lenguaje, prestando especial atención al tema de los manejadores (el equivalente a los punteros del código nativo) y al encajado y desencajado y consecuentemente cómo y dónde se asignan las variables dentro del .NET, en el segundo capítulo nos cuenta las extensiones del lenguaje.

Vemos las propiedades, los delegados y los eventos, los arrays CLI, todo ello mezclado y relacionado con el código nativo, las diferencias que hay entre los dos modelos y, sobre todo, profundizando sobre los temas tratados. Pero no al nivel del libro de Heege, sino que el tema viene tratado desde un punto de vista práctico, es decir, en relación a lo que un buen programador debe saber a la hora de conocer qué está usando y por qué está usando eso y no otra cosa. La verdad es que me asombra la profundidad y la sencillez con la que están expuestos los temas en todo el libro.

El último capítulo de la primera parte cubre lo que nos queda: la semántica de la pila y la destrucción determinista, la sobrecarga de funciones, los genéricos y las plantillas y cómo todo ello se interrelaciona entre sí, explicado con la profundidad adecuada para que sepamos cómo y por qué funcionan las cosas.

La segunda parte todavía es más interesante que la primera, y de hecho es el núcleo y razón de ser de todo el libro. El capítulo 4 nos habla de los punteros en .NET. Sí, de los punteros, ya que una referencia no es más que un puntero móvil, y como tal se puede fijar y operar con él como si fuera uno. O apuntar al interior de un objeto y trastearlo. Luego nos cuenta cómo utilizar una biblioteca nativa en un programa manejado y justo al revés, una biblioteca manejada en un programa nativo, y de paso nos explica cómo convertir variables nativas a manejadas y viceversa. El siguiente punto que trata es el uso de elementos nativos dentro de clases manejadas y de nuevo lo contrario, con todos los aspectos que debemos tener en cuenta a la hora de operar de esta forma. Incluso nos da clases que nos hagan de puente. Finalmente el capítulo termina explicándonos cómo podemos convertir delegados en punteros a funciones y cómo incluso podemos ejecutar un bloque de código nativo desde código manejado (cosa que haría saltar al DEP si se hiciera todo desde código nativo), etc. Verdaderamente apasionante, interesante y práctico (bueno, lo último no mucho).

En el quinto volvemos a la mezcla de código nativo y manejado, profundizando en las conversiones, para pasar a ver cómo podemos envolver una biblioteca nativa con un código en C++/CLI para que pueda ser utilizado por otros lenguajes .NET sin necesidad de Interop de ningún tipo, y finalmente termina explicándonos cómo envolver una DLL MFC y COM. El último punto que trata tiene un interés enorme: una misma DLL que se puede usar tanto para código manejado como nativo, todo un tour de forcé.

La tercera parte me ha resultado menos interesante, ya que es una cosa que al menos a mi no me importa mucho, pero que sí puede resultar valiosa para aquellos que tengan mucho código antiguo y quieran aprovechar las nuevas características del .NET 3.0 sin tener que reescribir toda su aplicación.

Tres capítulos que cubren cómo insertar controles .NET en un cuadro de diálogo MFC (y lo contrario, un control MFC en una Ficha manejada), lo mismo con una ventana WPF con y sin XAML, y finalmente repetimos, pero ahora con WCF. Evidentemente se tratan las tres combinaciones, código WPF/XAML/WCF en código C++/CLI que directamente no soporta dichas APIs, código WPF/XAML/WCF en código C++ nativo y sus inversas.

Resumiendo: un libro enormemente interesante que trata todos los temas desde un punto de vista práctico y útil y que, creo, no deja casi nada del lenguaje C++/CLI sin cubrir, incluso ampliándolo a veces mediante alguna que otra idea de concepto.

Verdaderamente resulta el libro de cabecera para cualquiera que desee aprender C++/CLI de verdad, tras haber estudiado cualquier otro libro básico o incluso las entradas de este BLOG.

El libro es este.

December 1, 2007

Hemos leído: Expert C++/CLI (Marcus Heege, Apress).

Filed under: Programación

Para empezar diremos que se trata de un libro muy técnico y demasiado avanzado en algunos aspectos, tanto, que más del 50% del mismo no te sirve para nada como conocimientos prácticos. Eso sí, el resto es toda una gozada en cuanto a detalles de esos que hacen que te tires un par de días buscando por qué te falla tu programa y qué estás haciendo mal, para descubrir una acumulación de características más o menos oscuras del lenguaje, de la herramienta de desarrollo, del sistema operativo o incluso de todos a la vez que determinan el fallo. Mención especial sobre este tipo de cosas es el capítulo dedicado a los destructores y a toda la parafernalia relativa al Dispose y compañía.

El libro presupone que sabes C++/CLI, y no poco. Apenas entra a nombrar características de C++ si no es cuando está explicando cosas relativas al Interop y que afecten directamente al propio C++/CLI. También está en cierta medida centrado en el .NET, o más bien en aquellos detalles del .NET que no están presentes en otros lenguajes pero sí en C++/CLI; al autor no se le caen los anillos si tiene que mostrarnos código MSIL o pseudocódigo para explicarnos alguna característica preponderante.

Los primeros capítulos son flojitos –es un decir-, y comienzan donde otros libros terminan: modelos de compilación, puntos de entrada manejados en DLL, envoltura de bibliotecas nativas, para luego pasar a contarnos un montón de cosas sobre los tipos del .NET, cómo se almacenan en memoria, diferencias entre tipos valor y tipos referencia y cosas así. La verdad es que esta parte se suele encontrar en la mayoría de libros generales sobre el tema, pero al estar enfocada a C++/CLI no creo que se cubra en muchos otros volúmenes.

Lo siguiente es una somera explicación de los ensamblados, la E/S, el modelo de excepciones, acceso a Web, funciones de ayuda integradas en el código y muy poco sobre ficheros de configuración. Otra vez algo que suele aparecer en otros libros, pero aquí está tratado de pasada, como si el autor lo mencionara para recordarnos lo que pudiéramos haber olvidado cuando estudiamos C#, o más bien nos viene a decir que en C++/CLI también tenemos de eso.

Y ya nos olvidamos de los caramelitos. Ahora viene el hardcore puro y duro. Un capítulo sobre ensamblados, cómo funciona la CAG, metadatos, reflexión y cosas de esas. Finaliza con un toque de serialización de componentes.

Estamos ya en el capítulo 5. Este también es otro capítulo típico, que no puede faltar en ningún libro, y es que nos cuenta sobre los tipos, cómo se inicializan, clases, herencia, componente, etc. Pero el modo de tratarlo no es el habitual, profundizando, sino que a vuelapluma nos explica que C++/CLI tiene de todo eso, y que si no los sabías, aquí no vas a encontrar quien te lo explique.

El siguiente capítulo tiene su miga. Se centra en aspectos técnicos sobre la construcción, cómo funciona el polimorfismo en C++/CLI y otros menesteres similares.

El tema de la integración con Visual Studio comienza, de nuevo, en donde otros libros terminan. Modelos de compilación, excepciones a través de ensamblados, mezcla de ficheros objeto nativos con manejados, ensamblados mixtos, cómo capturar excepciones de C++ y del Sistema Operativo dentro de un programa manejado (y viceversa), macros predefinidas y algo sobre plantillas. Ufff.

El siguiente también es típico, je je. Mezcla de tipos manejados y tipos nativos. Cómo tener un tipo manejado dentro de un tipo nativo, qué ocurre cuando tenemos un puntero a un tipo nativo dentro de uno manejado, objetos proxy, conversión de unos tipos en otros…

Y el que le sigue viene como consecuencia del anterior: transiciones manejadas/no manejadas. Cómo se producen, qué código se ejecuta y cómo. Por qué a veces se produce una doble o triple transición y la forma de evitarlas. Todo ello con medidas de tiempos (el código se publica al final del libro) y destripado de código vario.

Si yo digo: “Envolviendo bibliotecas nativas” todo el mundo sabe de qué hablo, ¿no? Pues no. Volvemos a empezar donde otros acaban, es decir, el autor supone que ya sabes hacerlo. Lo que no supone es que sabes cuales son las pifias y las ineficiencias más comunes.

Luego viene lo que he comentado en el primer párrafo y, aparte de los apéndices, el libro termina con jugoso capítulo explicando el startup de un programa .NET y mixto, es decir, destripa qué hace el cargador de arranque y qué hay antes del main() manejado y nativo. Toda una gozada.

Bueno, hasta aquí llegan las trescientas y pico páginas del libro técnico más denso que recuerdo haber leído (hay otro que se titula Arquitectura de computadores, que todavía no he leído –o más bien no he terminado de hacerlo-).

Es un libro que no recomiendo, por lo menos para avanzar en el estudio de C++/CLI, ya que, como he comentado, tiene poco de práctico, aunque su lectura y aprehensión significa una proeza intelectual bastante considerable.

La sensación que te da al leerlo es que el autor está tratando los temas por encima, de pasada y corriendo (salvo algunos capítulos concretos), lo que es completamente cierto. Como el API de Windows, sería más que una proeza llegar a aprender y conocer por completo y exhaustivamente todo lo que el .NET tiene para ofrecernos, sobre todo si nos centramos en los tiquismiquis del sistema.

Pues bien, hasta aquí llega esta entrada, y os emplazo para un futuro no muy lejano en el que comente dos nuevos libros, C++/CLI in action y mi actual libro de cuarto de baño: Reversing. Secrets of Reverse Engineering.

Se me olvidaba: el libro.

August 9, 2007

Fucowski. Memorias de un ingeniero

No, no me he equivocado de blog. Esta entrada va aquí. A sones de Música en torno a la Capilla Real de José Herrando, y por un fallo en la carga del iLiad (es decir, se me olvidó ponerlo a cargar al mediodía y se está cargando ahora), me he leído el libro del asunto de esta entrada en el ordenador (con un monitor plano de 24 pulgadas, una fuente bien gorda, y despachurrado en el sillón no se lee tan mal).

El libro no es un libro normal, o al menos no muy común en estos tiempos. Pese a estar en ese formato, no son más que algunas entradas del blog homónimo, con cierta continuidad más o menos hilada. Quizás alguien haya leído algún pedazo por ahí.

No voy a comentar nada sobre él. Mejor que lo leas. Te lo recomiendo encarecidamente, y sólo tardarás un par de horas. Depende de qué lado estés, te gustará o no, pero seguro que no te deja indiferente.

A mi me ha encantado, por el desparpajo del lenguaje. Por los giros. Como este, que no tiene que ver con el tema:

Lib me pasó mi guitarra y dijo:
-Tócame algo.
Yo dejé la guitarra en el suelo, y me lo tomé al pie de la letra.

Por la forma de narrar. Por lo crudo. Por las metáforas. Por todo.

Me he partido de la risa, sobre todo con la escena de los huevos. Y no porque sea humorística, no.

Por otra cosa.

Hazme caso y échale un vistazo.

Léelo.

Get free blog up and running in minutes with Blogsome
Theme designed by Gary Rogers