ENUNCIADO
Esta segunda práctica consiste en un programa que admite el
nombre de un fichero por la línea de órdenes de la shell.
Esta práctica no es para entregar.
Efectúa una proyección en memoria de dicho
fichero y sustituye
todas sus 'a' por 'o'. Deshace la proyección y cierra el fichero.
Comprobación de errores no paranoica.
¿Qué habría que usar para
hacer esto si no se dispusiera de ficheros proyectados en memoria
en el sistema operativo?
¿Qué ventajas suponen estos ficheros?
COMENTARIOS
La práctica con 0.25 es la de Strauss:
#define _HPUX_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main ( int argc, char *argv[] ) {
int archivo, tam_fich, i;
char mensaje[80];
char *buffer;
if ( argc==1 ) {
printf("Modo de uso:\n");
printf(" visuol_mem ARCHIVO\n");
return 0;
/* Los errores, deberían ir por el canal de errores.
fprintf(stderr, ...);
Además, el código de retorno 0 se reserva para ejecución
con éxito */
}
archivo=open( argv[1], O_RDWR );
if (archivo==-1) { /* Eeecc */
printf("Imposible abrir archivo.\n");
/* ¡¡¡Los errores, deberían ir por el canal de erroress!!! */
sprintf(mensaje, "%s: abrir : %s\n",argv[0],argv[1]);
perror(mensaje);
return 1;
}
tam_fich=lseek (archivo, 0, SEEK_END);
buffer=mmap (0, tam_fich , PROT_READ | PROT_WRITE , MAP_SHARED, archivo , 0);
close (archivo); /* Bien: no hace falta mantenerlo abierto */
if (buffer==MAP_FAILED) {
printf("Error de memoria");
/* ¡¡¡Los errores, deberían ir por el canal de erroress!!! */
sprintf(mensaje, "%s: memoria : %s\n",argv[0],argv[1]);
perror(mensaje);
return 1;
}
for (i=0; i<tam_fich; i++ )
if (buffer[i]=='a') buffer[i]='o';
munmap (buffer, tam_fich);
return 0;
}
MENCIONES ESPECIALES
Como nadie salvo dos grupos respondió a las preguntas de la práctica
daremos las menciones especiales a estos grupos:
- De Tacasama y Pirri (0.1 ptos.):
- ¿Qué habría que usar para
realizar esto si no se
dispusiera de ficheros proyectados en memoria en
el sistema operativo?
Primeramente deberíamos leer el contenido original
del fichero con la llamada al sistema read() que
vuelca el contenido en un buffer previamente declarado.
En el buffer se realizarían los cambios pertinentes.
Una vez hecho esto habría que volver a volcar todo
el contenido del buffer al fichero original con la
llamada al sistema write(), lo que supone escribir
de nuevo todo el fichero.
Parcialmente correcto.
No se debe usar búfer grande donde volcar completamente
el contenido de un fichero porque el fichero puede
ser muy grande y se gastaría mucha memoria dinámica
sin sentido. Lo más correcto es hacerlo con un búfer
más pequeño e ir cambiando el fichero a trozos.
- ¿Qué ventajas suponen estos ficheros?
La ventaja de los ficheros proyectados en memoria es
que todo cambio realizado en la memoria pasa
automaticamente a formar parte del fichero una vez
deshecha la proyección con la llamada al sistema
munmap(). De este modo nos ahorramos el gasto que
supone el uso de las llamadas al sistema read();
y write(); y tener que sobreescribir todo el contenido
del fichero para hacer un cambio por
mínimo que éste sea.
Semicorrecto de nuevo.
En ningún lugar de la página de manual de
munmap
se dice que los cambios realizados
sobre un fichero proyectado en memoria tomen su
efecto cuando se realice la llamada al sistema
munmap
. Además,
esto tendría poco sentido.
Van tomando efecto según se escribe.
- De Goku y Son Gohan (0.1 ptos.):
- ¿Qué habría que usar para realizar
esto si no se
dispusiera de ficheros proyectados en memoria en
el sistema operativo?
Habria que realizar un read para leer el fichero,
guardandolo en un buffer. Cambiar lo que se desee en el
buffer, guardar ese buffer en otro fichero distinto y
al finalizar cambiar ese fichero por el otro.
[[Acentos omitidos por el remitente]]
Parecida a la contestación
anterior. Aunque se dice de pasada, normalmente
se usa un búfer ni grande ni pequeño y el fichero
transformado no se va modificando sino que se crea
uno nuevo temporal y se cambia el nombre del nuevo
cuando se acaba.
- ¿Qué ventajas suponen estos ficheros?
En los proyectados el acceso es aleatorio, mientras
que de la otra forma seria secuencial.
[[Acentos omitidos por el remitente]]
Correcto.
En el proyectado el sistema operativo se encarga de
las operaciones de entrada-salida, de la otra forma se
tendria que encargar uno mismo de dichas operaciones.
[[Acentos omitidos por el remitente]]
En realidad lo que ocurre
es que con memoria mapeada el sistema operativo planifica
la entrada/salida. Con read
y
write
, también, pero
está más condicionado
por cómo y qué
read
s y writes
hacemos.
Proyectandolo solamente se utiliza un fichero, mientras
que en el otro modo se utilizan dos.
Proyectandolo se utiliza memoria virtual.
[[Acentos omitidos por el remitente]]
Usar memoria virtual no
es "per se" una ventaja. Las consecuencias de usar
memoria virtual son una mayor rapidez. El propio
hardware realizará las proyecciones. El trasvase
de datos será mínimo.
© 2000 Guillermo González Talaván.