sábado, 3 de abril de 2010

Encrucijada (I: Enunciado)

Hoy toca un post kilométrico que llevo demasiado tiempo pendiente, no se siquiera dejará publicar entero. Bueno, estoy pensando que, para evitar problemas la parte grande la voy a colocar en el siguiente.
En este caso se trata de la 2º práctica evaluable de la asignatura de Laboratorio de Sistemas Operativos de 2º de ITIS en la Universidad de Salamanca.
La práctica era bastante difícil, no vamos a negarlo, hasta el propio Guillermo se encontró con que era muy compleja. Decía así:

En la práctica anterior hubimos de sufrir la falta de medios para comunicar adecuadamente a los procesos entre sí. En esta práctica pondremos remedio a la situación permitiendo usar los nuevos mecanismos IPC recientemente aprendidos. Se tratará de regular la circulación en un cruce controlado por semáforos de tráfico.

En esta segunda práctica usaréis una biblioteca de enlazado estático que se os proporcionará. El objetivo es doble: por un lado aprender a usar una de tales bibliotecas y por otro descargar parte de la rutina de programación de la práctica para que os podáis centrar en los problemas que de verdad importan en esta asignatura.


El programa constará de un único fichero fuente, cruce.c, cuya adecuada compilación producirá el ejecutable cruce. Respetad las mayúsculas/minúsculas de los nombres.

Para simplificar la realización de la práctica, se os proporciona una biblioteca estática de funciones (libcruce.a) que debéis enlazar con vuestro módulo objeto para generar el ejecutable. Gracias a ella, algunas de las funciones necesarias para realizar la práctica no las tendréis que programar sino que bastará nada más con incluir la biblioteca cuando compiléis el programa. La línea de compilación del programa podría ser:
gcc cruce.c libcruce.a -o cruce
Disponéis, además, de un fichero de cabeceras, cruce.h, donde se encuentran definidas, entre otras cosas, las macros que usa la biblioteca y las cabeceras de las funciones que ofrece.

El proceso inicial se encargará de preparar todas las variables y recursos IPC de la aplicación y registrar manejadoras para las señales que necesite. Este proceso, además, debe tomar e interpretar los argumentos de la línea de órdenes y llamar a la función CRUCE_inicio con los parámetros adecuados. El proceso será responsable de crear los procesos adicionales necesarios. Cada peatón o cada coche simulado será representado mediante un proceso, hijo del proceso principal. También es responsabilidad del primer proceso el controlar que, si se pulsa CTRL+C la práctica acaba, no dejando procesos en ejecución ni recursos IPCs sin borrar. La práctica devolverá 0 en caso de ejecución satisfactoria o un número mayor que cero, en caso de detectarse un error.

La práctica se invocará especificando dos parámetros obligatorios desde la línea de órdenes. El primer parámetro será el número máximo de procesos que puede haber en ejecución simultánea. El segundo consistirá en un valor entero mayor o igual que cero. Si es 1 o mayor, la práctica funcionará tanto más lenta cuanto mayor sea el parámetro y no deberá consumir CPU apreciablemente. El modo de lograr esto lo realiza la propia biblioteca. Vosotros no tenéis más que pasar dicho argumento a la función de inicio. Si es 0, irá a la máxima velocidad, aunque el consumo de CPU sí será mayor. Por esta razón y para no penalizar en exceso la máquina compartida, no debéis dejar excesivo tiempo ejecutando en el servidor la práctica a máxima velocidad.

El programa debe estar preparado para que, si el usuario pulsa las teclas CTRL+C desde el terminal, la ejecución del programa termine en ese momento y adecuadamente. Ni en una terminación como esta, ni en una normal, deben quedar procesos en ejecución ni mecanismos IPC sin haber sido borrados del sistema. Este es un aspecto muy importante y se penalizará bastante si la práctica no lo cumple.

Es probable que necesitéis semáforos o buzones para sincronizar adecuadamente la práctica. En ningún caso podréis usar en vuestras prácticas más de un array de semáforos, un buzón de paso de mensajes y una zona de memoria compartida. Se declarará un array de semáforos de tamaño adecuado a vuestros requerimientos, el primero de los cuales se reservará para el funcionamiento interno de la biblioteca. El resto, podéis usarlos libremente.

La biblioteca requiere memoria compartida. Debéis declarar una única zona de memoria compartida en vuestro programa. Los 256 bytes primeros de dicha zona estarán reservados para la biblioteca. Si necesitáis memoria compartida, reservad más cantidad y usadla a partir del byte bicentésimo quincuagésimo séptimo.

Las funciones proporcionadas por la biblioteca libcruce.a son las que a continuación aparecen. De no indicarse nada, las funciones devuelven -1 en caso de error:
  • int CRUCE_inicio(int ret, int maxProcs, int semAforos, char *zona)
    El primer proceso, después de haber creado los mecanismos IPC que se necesiten y antes de haber tenido ningún hijo, debe llamar a esta función, indicando en ret la velocidad de presentación y en maxProcs el número máximo de procesos permitidos en esta ejecución (parámetros ambos de la línea de órdenes) y pasando además el identificador del conjunto de semáforos que se usará y el puntero a la zona de memoria compartida declarada para que la biblioteca pueda usarlos.
  • int CRUCE_pon_semAforo(int sem, int color)
    Pone el semáforo sem al color color. El primer parámetro puede ser: SEM_P1, SEM_P2, SEM_C1, SEM_C2, para los semáforos de peatones y coches, respectivamente. El segundo parámetro puede valer: ROJO,AMARILLO(solamente para los semáforos de coches) o VERDE. Estas son todas macros definidas en cruce.h.
  • int CRUCE_nuevo_proceso(void)
    El padre, después de haber creado todo lo necesario, se encuentra en un bucle infinito en el que va generando los nuevos procesos, coches o peatones. Esta función le devuelve COCHE o PEAToN para que sepa de qué tipo es el proceso que tiene que crear a continuación.
  • struct posiciOn CRUCE_inicio_coche(void) y struct posiciOn CRUCE_inicio_peatOn(void)
    El nuevo proceso hijo, dependiendo de si es coche o peatón, llamará a una de estas dos funciones. La función correspondiente devolverá las coordenadas de la posición siguiente del objeto recién creado. La funciónCRUCE_inicio_peatOn es desaconsejada. Úsese mejor la siguiente función.
  • struct posiciOn CRUCE_inicio_peatOn_ext(struct posiciOn *posNacimiento)
    El nuevo proceso hijo, si es un peatón, llamará a esta función. La función devolverá las coordenadas de la posición siguiente del peatón recién creado y la posición de nacimiento en el parámetro pasado por referencia. Esta función sustituye a la correspondiente del apartado anterior.
  • struct posiciOn CRUCE_avanzar_coche(struct posiciOn sgte) y struct posiciOn CRUCE_avanzar_peatOn(struct posiciOn sgte)
    El proceso, después de haber llamado a la función anterior, se mete en un bucle de avance. A esta función se le pasa la posición a la que se quiere ir y devuelve la nueva posición siguiente. Del bucle se saldrá cuando en la coordenada y de la posición devuelta haya un valor menor que cero.
  • int pausa_coche(void) e int pausa(void)
    Entre dos avances consecutivos, los coches llaman a la primera función y los peatones a la segunda. La segunda función también sirve para medir las pausas del ciclo semafórico
  • int CRUCE_fin_coche(void) e int CRUCE_fin_peatOn(void)
    El proceso hijo que haya salido del bucle de avance, invoca esta función.
  • int CRUCE_fin(void)
    El padre, una vez sabe que ha acabado la práctica y antes de realizar limpieza de procesos y mecanismos IPC debe llamar a esta función.
  • void pon_error(char *mensaje)
    Pone un mensaje de error en el recuadro azul de la parte inferior de la pantalla y espera a que el usuario pulse "Intro". La podéis usar para depurar.


Estad atentos pues pueden ir saliendo versiones nuevas de la biblioteca para corregir errores o dotarla de nuevas funciones.

El guión que seguirá el proceso padre será el siguiente:
  1. Tomará los datos de la línea de órdenes y los verificará.
  2. Iniciará las variables, mecanismos IPC, manejadoras de señales y demás.
  3. Llamará a la función CRUCE_inicio.
  4. Creará el proceso gestor semafórico.
  5. Entrará en un bucle infinito del que solamente saldrá si se pulsa CTRL+C. Dentro del bucle:
    1. Si hay tantos procesos como el máximo declarado, se queda esperando, sin consumo de CPU, hasta que muera alguno.
    2. Llamará a la función CRUCE_nuevo_proceso, que responderá indicando de qué tipo será: coche o peatón.
    3. Creará un proceso hijo, que ejecutará las funciones correspondientes a su tipo.
  6. Cuando se pulse CTRL+C, se engargará de finalizar todo ordenadamente.


Por su parte, el proceso gestor semafórico realizará lo que sigue en un bucle infinito:
  1. Establecerá el estado de los semáforos de tráfico según en la fase en que nos encontremos.
  2. Dormirá, sin consumo de CPU, el tiempo correspondiente a esa fase.


Finalmente, los procesos que circulan (peatones o coches), entrarán en un bucle después de llamar a su función de inicio. Dentro del bucle, llamarán a la función de pausa y a la de avance hasta que esta última devuelva un valor menor que cero en la coordenada y. El proceso acaba no sin antes llamar a la función de fin.

Observad que existe mucha sincronización que no se ha declarado explícitamente y debéis descubrir dónde y cómo realizarla. Os desaconsejamos el uso de señales para sincronizar. Una pista para saber dónde puede ser necesaria una sincronización son frases del estilo: "después de ocurrido esto, ha de pasar aquello" o "una vez todos los procesos han hecho tal cosa, se procede a tal otra".

Respecto a la sincronización interna de la biblioteca, se usa el semáforo reservado para conseguir atomicidad en la actualización de la pantalla y las verificaciones. Para que las sincronizaciones que de seguro deberéis hacer en vuestro código estén en sintonía con las de la biblioteca, debéis saber que sólo las funciones que actualizan valores sobre la pantalla están sincronizadas mediante el semáforo de la biblioteca.

En esta práctica no se podrán usar ficheros para nada, salvo que se indique expresamente. Las comunicaciones de PIDs o similares entre procesos, si hicieran falta, se harán mediante mecanismos IPC.

Siempre que en el enunciado o LPEs se diga que se puede usar sleep(), se refiere a la llamada al sistema, no a la orden de la línea de órdenes.

Los mecanismos IPC (semáforos, memoria compartida y paso de mensajes) son recursos muy limitados. Es por ello, que vuestra práctica sólo podrá usar un conjunto de semáforos, un buzón de paso de mensajes y una zona de memoria compartida como máximo. Además, si se produce cualquier error o se finaliza normalmente, los recursos creados han de ser eliminados. Una manera fácil de lograrlo es registrar la señal SIGINT para que lo haga y mandársela uno mismo si se produce un error.

Ciclo semafórico

En la práctica hay cuatro semáforos de tráfico, dos de peatones (P1 y P2) y dos de automóviles (C1 y C2):


El ciclo semafórico pasa por tres fases principales:
  • Primera fase: C1 y P2 en verde. El resto, en rojo. Duración: 6 pausas(*).
  • Segunda fase: C2 en verde. El resto, en rojo. Duración: 8 pausas.
  • Tercera fase: P1 en verde. El resto, en rojo. Duración: 12 pausas.
(*) Una pausa equivale a una llamada a la función pausa().

Biblioteca de funciones libcruce.a

Con esta práctica se trata de que aprendáis a sincronizar y comunicar procesos en UNIX. Su objetivo no es la programación, aunque es inevitable que tengáis que programar. Es por ello que se os suministra una biblioteca estática de funciones ya programadas para tratar de que no debáis preocuparos por la presentación por pantalla, la gestión de estructuras de datos (colas, pilas, ...) , etc. También servirá para que se detecten de un modo automático errores que se produzcan en vuestro código. Para que vuestro programa funcione, necesitáis la propia biblioteca libcruce.a y el fichero de cabeceras cruce.h. La biblioteca funciona con los códigos de VT100/xterm, por lo que debéis adecuar vuestros simuladores a este terminal. También se usa la codificación UTF-8, por lo que necesitáis un programa de terminal que sepa interpretarlos. Los terminales de Linux lo hacen por defecto, pero si usáis Windows, debéis aseguraros de que el programa tiene capacidad para interpretarlos y que esta capacidad está activada. Si no es así notaréis caracteres basura en la salida de modo que no se verá nada.
Ficheros necesarios:
Registro de versiones:
  • 1.0: primera versión
  • 1.1: un error hace que no se reconozca bien al padre en CRUCE_nuevo_proceso
  • 1.2: la biblioteca tenía preferencia por sacar coches en la dirección horizontal
  • 2.0: para controlar el nacimiento de los peatones es necesario conocer no solamente su posición siguiente, sino también, su posición de nacimiento. Para ello, se crea una nueva función: CRUCE_nuevo_peatOn_ext

Nintendo 3DS, Opiniones

A ver, ¿por dónde empezamos? Nintendo, la empresa japonesa reina del entretenimiento electrónico hace unos días que volvió a sorprender al mundo con su última creación, de la que, todo sea dicho, no tenemos apenas datos.
Solamente sabemos que va a ser compatible con los anteriores modelos NDS, NDSL, NDSi y NDSi XL de lo que deducimos que tendrá 2 pantallas, que va a funcionar mediante cartuchos, y que sus pantallas van a ser capaces de reproducir gráficos 3D sin necesidad de gafas especiales. El resto no son más que rumores y habladurías.
Y ahora es cuando os digo que, los que me prestarais un poco de atención hace 2 ó 3 años os habréis dado cuenta de que en esa época me dio por decir que la siguiente portátil de Nintendo tendría alguna forma de holografía en la pantalla inferior. Bueno, pues parece que me equivoqué en parte.
En mi mente, el 3D se daría saliendo de la "pantalla" a modo de mapa o algo así. Y por lo visto va a ser al contrario, se verá hacia dentro. Aunque aún es pronto ya que no sabemos cómo van a ser las pantallas, y cuando lo sepamos, los vídeos no nos dirán nada porque no lo veremos en directo.
De todas maneras creo que Nintendo, hasta ahora, lo ha hecho bastante bien. No ha confirmado nada, aunque era un secreto a voces, sobre la nueva portátil, hasta que no ha tenido confirmación de que la podía vender durante el presente año fiscal.
Veremos dónde quedan las promesas, de lanzamiento, de gráficos, de innovación... La Wii prometía mucho, y muchas de esas promesas quedaron en humo solamente. Pero para Nintendo fue una gran táctica, algo de lo que opinaré en otro post.
Sólo espero que cumplan las fechas y no nos hagan esperar mucho, y por supuesto que no se pasen con el precio. Nintendo no suele poner precios abusivos, pero siempre hay una 1º vez para todo, sobre todo tratándose de dinero, y no sería bueno para la empresa, pero sobre el futuro no hay nada escrito y las guerras son crueles, incluso las de consolas. Hay competidores que quedan en el camino cuando nadie se lo espera...

April Fool's Day 2010

Se que los buenos seguidores de este blog echaríais de menos que el 1 de Abril publicara un post crítica a esa estúpida tradición. Pero en realidad, no tenia gran cosa de la que quejarme sobre ello ya que, en contra de la normalidad, no leí ninguna noticia fruto del día. Así que, supongo que no tenía demasiados motivos.
Ayer y hace un rato si que he leído alguna noticia, ya tachada, del 1 de Abril. Pero pocas, la verdad. Debe ser que la gente ya se ha cansado o tiene cosas más importantes en que pensar...

jueves, 1 de abril de 2010

Youtube estuvo caído unas horas


Pues sí mis queridos lectores, el otro día me encontré con que Youtube, una de las páginas más visitadas de internet (de Google obviamente) estaba caida. Si os digo la verdad no me acuerdo exactamente cuando, porque pensé poner esto en el momento, pero como siempre, lo dejé para más adelante.
Pero, Ubuntu es muy listo y un chivato, y me dice que la imágen la tomé el jue 25 mar 2010 13:15:49 CET. Así que ya sabéis. A través de ese timestamp legible deducimos la fecha en la que Youtube estuvo caído.
Lo gracioso es que lo descubrí porque en los foros de EOL la gente se quejaba de que no lograban entrar a cinetube y a pornotube xD, si no, probablemente no habría ido a youtube a pornerme música xD.

miércoles, 31 de marzo de 2010

Desordenado mi cuarto, desordenado mi cerebro, ¿desordenada mi alma?


Bueno, ya veis, eso es una parte de mi cuarto. El resto está igual. Y... he pensado esta mañana que mi cerebro está igual. En ambos sitios hay demasiadas cosas, todas amontonadas en un desorden caótico, se te vienen encima a la menor ocasión.
Y no es que estén colocadas de una manera lógica ni nada. Siempre suelo acabar encontrando cualquier cosa que busco pero, simplemente están así.
Al igual que resulta casi imposible entrar en mi cuarto, lo es entrar en mi cabeza. Las pilas de tareas, de cosas por hacer, se amontonan. Los pensamientos ya ni siquiera pueden fluir con cierta agilidad. Ahora mismo me estalla la cabeza por un lado.
Me disperso y se me van los pensamientos de la cabeza. No soy capaz de centrarme en algo y cada vez se amontonan más cosas.
Mañana voy a hacer otra de esas cosas de las que se, ya de primeras, que me voy a acabar arrepintiendo, pero que "me obligan" a hacer.
Parece que últimamente mi vida ha vuelto a la rutina de las compras. De nuevo todos los días una nueva compra. Supongo que es por lo de siempre, pero nada de lo que hago consigue cambiar mi interior.
Demasiadas dudas, heridas, tareas... No consigo montar el puzzle de mis ideas, sigo sin saber quién soy y por qué he de seguir aquí. Cada vez me parezco más un extraño a mi mismo, que se deja llevar por las corrientes de la vida, sin nada a lo que aferrarse. Sin nada más que los recuerdos que parece que es lo único que tengo...
Se que debo hacer una ordenación de mi habitación, también de mi cabeza, pero es algo mucho más complejo que una ordenación de burbuja. Ójala existiera un QuickShort para la vida, para el alma, para las habitaciones, y para el cerebro...

30-4-2010 Comienza el fin del mundo

Esta mediodia se ha producido el primer choque de haces de protones a energías desconocidas hasta ahora. Cada haz tenía 3,5 TeV y por lo tanto se ha logrado un choque a 7 TeV.
Esto no solo representa un record para la física moderna, sino que, además, ha arrojado una gran cantidad de resultados nuevos que servirán de estudio durante mucho tiempo.
Pero el acelerador no se detuvo con un choque. Todos los detectores tuvieron la suerte de experimentar este hecho muchas veces durante la tarde, y esta noche, el acelerador seguirá produciendo choques y resultados.
Estos choques son los que pueden producir el fin del mundo xD. Aunque estos no son los que llegará a producir el acelerador, de hasta 14 TeV dentro de unos años.
Por suerte o por desgracia, no han acabado con el mundo. Igual mañana no existimos, pero las posibilidades son demasiado remotas como para tenerlas en cuenta.
Hablando en serio, los logros del acelerador hoy han sido muy grandes. Hubiera sido muy bueno estar en la sala de control cuando ese primer choque fue detectado, rompiendo los límites impuestos hasta ese momento, haciendo historia, haciendo que los 3000 millones de € merecieran la pena.
Enhorabuena a los que han hecho posible ese gran avance y con mucha envidia seguiré mirando periodicamente sus avances desde la lejanía de Salamanca, soñando algún día estar en algún lugar como ese, ser una infímisima parte de la historia, estar en la historia de manera anónima, y por supuesto, poder jugar con el juguete de Dios...

Aquí podéis leer algo más sobre el asunto.

Kim Possible Opening