viernes, 2 de diciembre de 2011

Práctica 3

Contesta las siguientes preguntas.

1.Disponemos de un disco duro de 20 GB de capacidad. Hay establecida sobre él, una única partición que contiene un sistema de ficheros del tipo FAT32 en el que cada agrupamiento (cluster) consta de 16 sectores de 512 bytes cada uno. ¿Cuántos sectores del disco se necesitarán para almacenar cada copia la FAT? Razona tu respuesta.

FAT = 32 bits
Capacidad = 20 GB
Agrupamiento = (16 * 512 Bytes)
Sectores = 16
(Capacidad / agrupamiento) * Sectores

20GB / (16*512)
(20 * 2¹) /
(20* 2¹ * 32)/
(20 * 2¹) / (16 *512)
10485760/8192 = 1280 *16

R = 20480 Sectores

2.La policía ha arrestado al sospechoso de un delito. Al analizar el contenido de su ordenador piensan que pueden inculparle pues el contenido del mismo

es el siguiente: 

Número  De bloque de datos
Contenido
10
he
11
sido
12
yo
13
no
14
sigan
15
buscando


Como experto informático, pides consultar el contenido de la FAT, que es el siguiente: 

Número  de entrada en la FAT
Contenido
10
11
11
EOF
12
13
13
10
14
15
15
12

 ¿Apoyarías la opinión de la policía? Razona tu respuesta. 

No porque no es culpable ya que en un archivo FAT los bloques se asignan como una lista enlazada que finaliza en EOF y la reconstrucción de estos bloques son: 

Sigan
Buscando
Yo
No
He
sido

14
15
12
13
10
11
EOF



Este código contiene errores y está incompleto. Corrige y completa. Haz que el hilo consumidor muestre en pantalla todos los datos producidos por el hilo
productor.

A continuacion se muestra el codigo coregido y completo asi como la ejecucion de este.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#define MAX 10
#define FIN -1
 int buffer[MAX];
 sem_t huecos, elementos;
 int generar_dato (void)
 {
  return random() %256;
 }
 int numero_aleatorio(void)
 {
  return random() %100;
 }
 void *productor (void *p)
 {
  int pos_productor= 0;
  int num, dato, n;
  n= numero_aleatorio();
  printf ("Productor con %d datos\n", n);
  for(num= 0; num< n; num++)
  {
   dato= generar_dato();
   sem_wait(&huecos);
   buffer[pos_productor]= dato;
   pos_productor= (pos_productor+ 1) %MAX;
   sem_post (&elementos);
  }
  sem_wait (&huecos);
  buffer[pos_productor]= FIN;
  sem_post (&elementos);
  pthread_exit (NULL);
 }
 void *consumidor(void *p)
 {
  int pos_consumidor= 0, dato;
  bool continuar= true;
  while (continuar)
  {
   sem_wait (&elementos);
   dato= buffer[pos_consumidor];
   sem_post (&huecos);
   if (dato== FIN)
    continuar= false;
   else
   {
    printf ("Numero aleatorio: %d\n", dato);
    pos_consumidor= (pos_consumidor+1) %MAX;
   }
  }
  pthread_exit (NULL);
 }
 int main ()
 {
  pthread_t hiloproductor, hiloconsumidor;
  sem_init (&elementos, 0, 0);
  sem_init (&huecos, 0, MAX);
  pthread_create (&hiloproductor, NULL, productor, NULL);
  pthread_create (&hiloconsumidor, NULL, consumidor, NULL);
  pthread_join (hiloproductor, NULL);
  pthread_join (hiloconsumidor, NULL);
  sem_destroy (&huecos);
  sem_destroy (&elementos);
  return 0;
 }

jueves, 24 de noviembre de 2011

Práctica 2

Estudia el siguiente codigo y escribe la jerarquia de procesos resultante. Despues, compila y ejecuta el codigo para comprobarlo (deberas añadir llamadas al sistema getpid, getppid y wait para conseguirlo).

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define L1 2
#define L2 3
int main ()
{
int cont1, cont2;
pid_t pid;
for (cont2= 0; cont2< L2; cont2++)
{
for (cont1= 0; cont1< L1; cont1++)
{
pid= fork();
if (pid== 0)
break;
}
if (pid!= 0) break;
}
printf ("Soy el hijo: %d y Mi padre es: %d.\n", getpid(), getppid()); //Llamadas al sistema getpid, getppid
if (pid!= 0)
for (cont1= 0; cont1< L1; cont1++)
printf ("Fin del proceso%d.\n", wait (NULL)); //Llamada al sistema de wait
return 0;
}

Resultado de la ejecución del código anterior.

El arbol de jerarquia queda de la siguiente manera.




miércoles, 23 de noviembre de 2011

Actividad 1

Dibuja la jerarquía de procesos que resulta de la ejecución del siguiente código. Introduce las llamadas al sistema wait para que una vez generado el árbol de procesos los hijos sean esperados por sus respectivos padres. Ademas,  haz que se informe de los tiempos de ejecución de las aplicaciones  xload y kcalc que se generen así como del tiempo total de ejecución. Para calcular el  tiempo transcurrido, puedes utilizar la función time() de la librería estándar  time.h. La llamada time(NULL) devuelve los segundos transcurridos desde las 00:00:00 del 1/1/1970 hasta el instante de la llamada.

Código que crea la jerarquia de procesos

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (int argc, char *argv[])
{
         int i, j;
         pid_t pid, nuevo, nuevo1;
         time_t ini, fin;
         ini= time(NULL);
         for (i= 0; i< 2; i++)
         {
                   pid= getpid();
                   for (j= 0; j< i+2; j++)
                   {
                            nuevo= fork();
                            if(nuevo== 0)
                            {
                                      break;
                                      nuevo1= fork();
                                      if(nuevo1== 0)
                                               execlp ("xload", "xload", NULL);
                            }
                   }
                   if (pid!= getpid())
                            execlp ("kcalc", "kcalc", NULL);
         }
         for (i= 0; i< 2; i++)
         for (j= 0; j< i+2; j++)
         {
                   wait(NULL);
         }
         printf ("Tiempo total: %ld\n", time(NULL)-ini);
         printf("Soy el hijo : %d y Mi padre es : %d\n",getpid(),getppid());
         sleep(3);
         return 0;
}

Del código anterior el resultado de su ejecucuión fue:... En sus primera ejecución...


Segunda ejecución...



Y el arbol de jerarquias de procesos de la primera ejecucion queda así:

miércoles, 12 de octubre de 2011

Diferencia entre FIFO y LIFO

FIFO. (First In, First Out - Primero en entrar, primero en salir). Esta  estructura se utiliza  en colas y la definición de FIFO quiere decir que en una cola los datos se almacenan de tal forma que al recuperarlos, estos serán devueltos en el mismo orden a como se fueron almacenando. Se suele implementar en programación con el uso de vectores o punteros.
LIFO. (Last In, First Out – Último en entrar primero en salir). Esta estructura se utiliza en una pila y la definición de LIFO quiere decir que en una pila se podrá almacenar elementos de tal forma que cuando se quiera recuperar, estos serán devueltos en orden inverso a como fueron almacenados.

Diferencia
  • El orden de devolución de elementos es diferente
  • FIFO Primero en entrar, primero en salir.
  • LIFO  Último en entrar primero en salir.
  • La estructura FIFO se utiliza en una cola.
  • La estructura LIFO se utilizan en una fila.



martes, 27 de septiembre de 2011

POSIX

¿Qué es?

POSIX es el acrónimo de Portable Operating System Interface; la X viene de UNIX como seña de identidad de la API(es la abreviatura de Aplication Programming Interface. Un API no es más que una serie de servicios o funciones que el Sistema Operativo ofrece al programador, como por ejemplo, imprimir un carácter en pantalla, leer el teclado, escribir en un fichero de disco, etc.).

El POSIX Se trata de un estándar que intenta asegurar la portabilidad entre diferentes sistemas operativos. Dentro del estándar se especifica el comportamiento de las expresiones regulares y de las herramientas más comunes que las usan.

Así mismo define un estándar de llamadas al sistema operativo. La librería estándar de C define unas funciones que deben estar en cualquier entorno de desarrollo de C.

El término fue sugerido por Richard Stallman en respuesta a la demanda de la IEEE, que buscaba un nombre fácil de recordar. Una traducción aproximada del acrónimo podría ser “Interfaz para Sistemas Operativos migrables basados en UNIX”.
 
Pequeña Introducción

Estos son una familia de estándares de llamadas al sistema operativo definido por el IEEE y especificado formalmente en el IEEE 1003. Persiguen generalizar las interfaces de los sistemas operativos para que una misma aplicación pueda ejecutarse en distintas plataformas. Estos estándares surgieron de un proyecto de normalización de las API y describen un conjunto de interfaces de aplicación adaptables a una gran variedad de implementaciones de sistemas operativos.

Especifica las interfaces de usuario y software al sistema operativo en 15 documentos diferentes. La línea de comandos estándar y las interfaces de scripting se basaron en Korn Shell. Otros programas a nivel de usuario (user-level), servicios y utilidades incluyen AWK, echo, ed y cientos de otras. Los servicios a nivel de programa requeridos incluyen definición de estándares básicos de I/O, (file, terminal, y servicios de red). También especifican una API para las bibliotecas de threading, que es muy utilizada en una gran variedad de sistemas operativos.

Una serie de pruebas acompañan al estándar POSIX. Son llamadas “PCTS” en alusión al acrónimo “Posix Conformance Test Suite”. Desde que la IEEE empezó a cobrar altos precios por la documentación de POSIX y se ha negado a publicar los estándares, ha aumentado el uso del modelo Single Unix Specification. Este modelo es abierto, acepta entradas de todo el mundo y está libremente disponible en Internet. Fue creado por The Open Group.

¿Dónde se ocupa?

Sincronización de procesos. Define funciones para permitir la sincronización de procesos a través de semáforos contadores.

Memoria compartida. Tienen espacios de direccionamiento que son independientes entre sí. Sin embargo, muchas aplicaciones de tiempo real (y también muchas que no son de tiempo real) necesitan compartir grandes cantidades de datos de una manera eficiente.

Señales de tiempo real. Permite notificar eventos que ocurren en el sistema, pero no es completamente satisfactorio para aplicaciones de tiempo real. Las señales no se almacenan en colas y, por tanto, algunos eventos se pueden perder. Las señales no están priorizadas, y esto implica tiempos de respuesta más largos para eventos urgentes.

Comunicación de procesos. Se especifica un mecanismo sencillo de colas de mensajes para la comunicación entre procesos. Las colas de mensajes están identificadas por un nombre perteneciente a un espacio de nombres dependiente de la implementación.

Entrada/Salida Asíncrona. Define funciones que permiten solapar el procesado de aplicaciones con las operaciones de entrada/salida iniciadas por la aplicación. Una operación de entrada/salida asíncrona es similar a las operaciones de entrada/salida normales, con la excepción de que una vez que la operación asíncrona ha sido iniciada por un proceso, este proceso no se suspende y puede continuar ejecutando instrucciones, en paralelo con la operación de entrada/salida

Extensión de threads. Define interfaces para soportar múltiples actividades concurrentes, denominadas threads, dentro de cada proceso POSIX. Los threads definidos en el POSIX  tienen un estado asociado más pequeño que el de un proceso. Todos los threads que pertenecen al mismo proceso comparten el mismo espacio de direccionamiento. Pueden ser implementados con tiempos de cambio de contexto y de creación y destrucción más bajos que los de los procesos. El POSIX.4a ha sido específicamente desarrollado para abordar las necesidades de los sistemas multiprocesadores de memoria compartida.

Ejemplo

El ejemplo es un sistema productor-consumidor con búfer circular utilizando hilos, semáforos POSIX binarios y semáforos POSIX genérico

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <semaphore.h>
#include <pthread.h>
#define TAMBUF 8     // Tamaño del búfer circular
#define NUMDATOS 100 // Número de datos a enviar
// El buffer circular y los correspondientes punteros
int buffer[TAMBUF];
int bufin = 0;
int bufout = 0;
// Semaforo binario
pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
// Variable suma
int sum = 0;
// Semaforos generales
sem_t hay_datos;
sem_t hay_sitio;
// Funciones de escritura y lectura del buffer circular
void obten_dato(int *itemp)
{
  pthread_mutex_lock(&buffer_lock);
  *itemp = buffer[bufout];
  bufout = (bufout + 1) % TAMBUF;
  pthread_mutex_unlock(&buffer_lock);
  return;
}
void pon_dato(int item)
{
  pthread_mutex_lock(&buffer_lock);
  buffer[bufin] = item;
  bufin = (bufin + 1) % TAMBUF;
  pthread_mutex_unlock(&buffer_lock);
  return;
}
// Funciones productor-consumidor
void *productor(void *arg1)
{
  int i;
  for (i = 1; i <= NUMDATOS; i++)
  {
    sem_wait(&hay_sitio);
    pon_dato(i*i);
    sem_post(&hay_datos);
  }
  pthread_exit( NULL );
}
void *consumidor(void *arg2)
{
  int i, midato;
  for (i = 1; i<= NUMDATOS; i++)
  {
    sem_wait(&hay_datos);
    obten_dato(&midato);
    sem_post(&hay_sitio);
    sum += midato;
  }
  pthread_exit( NULL );
}
// Funcion principal
void main(void)
{
  pthread_t tidprod, tidcons;
  int i, total;
  total = 0;
  for (i = 1; i <= NUMDATOS; i++)
    total += i*i;
  printf("El resultado deberia ser %d\n", total);
// Inicializacion de semaforos
  sem_init(&hay_datos, 0, 0);
  sem_init(&hay_sitio, 0, TAMBUF);
// Se crean los hilos
  pthread_create(&tidprod, NULL, productor, NULL);
  pthread_create(&tidcons, NULL, consumidor, NULL);
// Se espera a que los hilos terminen
  pthread_join(tidprod, NULL);
  pthread_join(tidcons, NULL);
  printf("Los hilos produjeron el valor %d\n", sum);
}





Fuentes.
 
http://infogeekcatamarca.wordpress.com/2010/07/26/%C2%BFque-es-posix/
http://isa.umh.es/asignaturas/sitr/TraspSITR_POSIX1_procesos.pdf
http://www.infor.uva.es/~benja/apuntes-semaforos-POSIX.html