SISTEMAS OPERATIVOS II

Tercer curso Ingeniería Informática. Curso 2009-2010

Práctica 2: Procesos en Unix: Memoria

Continuar la codificación de un intérprete de comandos (shell) en UNIX, la funcionbalidad de la presente practica se aAÑADIRÁ a la de la práctica anterior. Como en la práctica anterior los comandos aquí descritos deben interpretarse de la siguiente manera

Además deben tenerse en cuenta las siguientes indicaciones

En esta práctica el shell tendrá capacidad para crear y acceder a sistemas de ficheros implementados sobre zonas de memoria compartida; el comando memfs crea, formatea y permite acceder a los ficheros en dichos sistema de ficheros. El shell llevará además una lista (de implementación libre) de las direcciones de memoria compartida que tiene mapeadas y de las que se asigna con el comando mem (tanto las obtenidas con mem -malloc como las obtenidas con mem -mmap)

Comandos a implementar en esta práctica

mem
[-malloc|-free|-mmap|-munmap|-show|-display] [arg...] Asigna (o desasigna) memoria para el shell y mapea o desmapea ficheros dentro del espacio del shell. Permite además ver las direcciones de memoria asignadas

iofile
[-read|-wite] file dir [cont] [-o]] Lee (o escribe) un fichero en (o desde) una posioción de memoria

memfs
[-create|-copy|-move|-delete|-list|-clear] [arg1...]

rec [-a|-n|-d]
[-sN] n Invoca a la función recursiva n veces, la opción -a, -n o -d indica si la memoria asignada con malloc en dicha función debe liberarse (a)ntes de la siguiente llamada recursiva, (d)espués o (n)o liberarse. Si no se indica una opción se supone que la memoria se libera despues de la llamada (-d). En parámetro -sN indica cuanto tiempo (en segundos) debe esperar la última llamada antes de terminar. (por ejemplo -s10 indicaría que la ultima iteracción de la función recursiva debería hacer una espera, (mediante sleep, de 10 segundos. La función recursiva recibe tres parámetros: uno que indica el número de veces que se tiene que invocar, otro que indica cuando liberar la memoria asignada con malloc y un tercero que indica cuanto tiene que esperar la última iteración Además esta función tiene 3 variables, un array automatico de 1024 caracteres, un array estático de 1024 caracteres y un puntero a caracter.

Esta función debe hacer lo siguiente

  1. asignar memoria (mediante malloc) al puntero para 1024 caracteres.
  2. imprimir
    • el valor del parámetro que recibe así como la dirección de memoria donde se almacena.
    • el valor del puntero así como la dirección de memoria donde se almacena.
    • la dirección de los dos arrays (el nombre del array como puntero).
  3. si se ha especificado la opción -a liberar la memoria asignada al puntero.
  4. invocarse a si misma con (n-1) como parámetro (si n>0).
  5. si es la última iteración (n=0) y se ha especificado -sN esperar N segundos (por medio de sleep).
  6. si se ha especificado la opción -d liberar la memoria asignada al puntero.

Un posible código para la función recursiva (sin las definiciones de constantes) podría ser:

void recursiva (int n, int liberar, int delay)
{
char automatico[TAMANO]; 
static char estatico[TAMANO]; 
void * puntero;

puntero=(void *) malloc (TAMANO);
printf ("parametro n:%d en %p\n",n,&n);
printf ("valor puntero:%p en direccion: %p\n", puntero,&puntero);
printf ("array estatico en:%p \n",estatico);
printf ("array automatico en %p\n",automatico);
if (liberar==ANTES)
   free (puntero);
if (n>0)
   recursiva(n-1,liberar,delay);
if (liberar==DESPUES)
   free (puntero);
if (n==0 && delay)        /* espera para la ultima recursividad*/  
   sleep (delay);
}

NOTAS SOBRE LOS IDENTIFICADORES DE MEMORIA id_mem Y LOS DE FICHEROS id_fich

id_mem
puede representar una dirección de memoria o una clave. Para distinguir si es una dirección o una clave se procede de la siguiente manera: se supone que es una dirección y se comprueba si está en la lista de direcciones de memoria compartida mapeadas; si está, es una dirección válida y se usa; si no está, se supone que es una clave y se vuelve a obtener un identificador con shmget y una dirección con shmat y se añade a la lista (evidentemente esto puede suponer tener mapeada la misma zona de memoria compartida en varios sitios). IMPORTANTE: SI SE SUMINISTRA UNA CLAVE SE VUELVE A MAPEAR. Tambien debe tenerse en cuenta que un puntero a caracter no se almacena en la direccion de memoria representada por la cadena por él apuntada. (char *p="0x004b0000" no quiere decir que la cadena apuntada por p esté en la dirección de memoria 0x004b0000). Un posible código para obtener una dirección a partir de un identificador pordría ser:

void * ObtenerMemoria (char * idmem, int tam)
{
  void * p;
  key_t cl;
  
  p=(void *) strtoull(idmem,NULL,16);

  if (EstaEnListaShareds(p))
  	return p;
  cl=(key_t) strtoul (idmem,NULL,10);
  return (ObtenerMemoriaShmget(cl,tam));
}
id_fich
La identificación de un fichero se supone que es de la forma id_mem:nombre_fichero, donde id_mem es un identificador de memoria tal como acaba de describirse y nombre_fichero es el nombre del fichero en el sistema de ficheros representado por id_mem. Si no se especifica id_mem se entiende que es un fichero de disco.

Ejemplos 10:p1.c; 0xd7ac0000:p2.c, p4.c ...

Información detallada de las llamadas al sistema y las funciones de la librería debe obternerse con man (mmap, munmap, shmget, shmat, shmctl, read, write...)

FORMA DE ENTREGA Va a ser utilizado el servicio de recogida de prácticas suministrado por el Centro de Cálculo de esta Facultad y parte del proceso de corrección de las prácticas va a ser automtico (compilación, listado de practicas entregadas etc) por lo cual deben entregarse exactamente como se indica a continuación:

FECHA DE ENTREGA VIERNES 14 MAYO DE 2010