Solución del examen de Tercera Convocatoria

Anuncio
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
[Cuestión 1.]
Resuelva con una línea de comandos UNIX los siguientes apartados.
Apartado A.- Muestre por la salida estándar la cadena NU:IC, donde NU es el nombre del usuario en el sistema e IC es la
ruta del intérprete de comandos que utiliza.
echo $USER:$SHELL
Apartado B.- Copie todo el contenido del directorio práctica situado en su directorio HOME al directorio /tmp
cp –r $HOME/practica/* /tmp
Apartado C.- Concatene los ficheros logs1.txt y logs2.txt en un nuevo fichero logs.txt con las líneas numeradas.
cat logs1.txt logs2.txt | cat –b > logs.txt
Apartado D.- Obtenga un listado de todos los ficheros de su directorio HOME (a cualquier nivel) excepto los
ficheros de código fuente (.c)
ls –Rl $HOME | grep “^-” | grep –v “\.c$”
Puntuación: 2 ptos.
Tiempo estimado: 10 min.
1
2
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
[Cuestión 2.]
Debe implementarse en C un programa denominado listado, que admita como parámetro la ruta
relativa de un directorio y que cree un proceso hijo que se encargue de almacenar en el fichero listado.txt la ruta y el tamaño en
bytes de los ficheros regulares contenidos en dicho directorio. Una vez finalizada dicha tarea deberá enviar al proceso padre la
señal SIGUSR1; el padre una vez que reciba dicha señal deberá añadir al fichero listado.txt la ruta y el tamaño en bytes de los
directorios contenidos en el directorio indicado en la línea de comandos. Así mismo debe considerar que el padre deberá instalar
un manejador denominado fin_hijo cuya misión será recoger el estado de terminación del proceso hijo. En la figura 1 se muestra
un esquema del ejercicio:
SIGCHLD
Padre
(2) listado de
directorios
SIGUSR1
listado.txt
Hijo
(1) listado de
ficheros regulares
Figura 1: Esquema del programa listado.
Si se ejecuta el programa listado sin indicar ningún argumento adicional, se mostrará por la salida estándar de
error el siguiente mensaje:
Uso: listado <directorio>
En la figura 2 aparece un ejemplo de ejecución de este programa:
murillo:/export/home/examen> ./listado .
Directorio = .
murillo:/export/home/examen> more listado.txt
Ruta del archivo regular = ./main.c Tamanno = 3697 bytes
Ruta del archivo regular = ./listado Tamanno = 9232 bytes
Ruta del archivo regular = ./listado.txt Tamanno = 117 bytes
Ruta del directorio = ./. Tamanno = 512 bytes
Ruta del directorio = ./.. Tamanno = 512 bytes
Figura 2: Ejemplo de ejecución del programa listado.
NOTAS:
−
Debe comprobarse que el segundo argumento que se indica en la línea de comandos es un directorio.
−
Antes de comenzar a procesar las entradas de directorio debe redireccionar la salida estándar al fichero listado.txt.
−
Considere que el manejador fin_hijo ya está definido, por lo tanto únicamente tendrá que instalarlo.
−
Se recomienda definir dos variables globales, una para almacenar el directorio que hay que procesar y otra para el
descriptor de fichero.
−
Sólo es posible emplear el tratamiento de los ficheros a bajo nivel.
−
No se puede utilizar la llamada a system ni a sleep.
Puntuación: 2 ptos.
Tiempo estimado: 30 min.
#include <stdio.h>
#include <sys/stat.h>
#include <sys/file.h>
3
#include
#include
#include
#include
#include
<dirent.h>
<fcntl.h>
<errno.h>
<unistd.h>
<signal.h>
#define LONGITUD_MAX 255
#define LISTADO "listado.txt"
void obtener_entradas_directorio (char *directorio, int df, int tipo_entrada);
void manejador (int s);
void fin_hijo(int s);
// Variables globales
int fd;
char directorio[255];
int main(int argc, char* argv[])
{
struct stat atributos;
pid_t retorno;
if (argc != 2)
{
fprintf(stderr, "Uso: %s <directorio>\n", argv[0]);
exit (-1);
}
// Obtenemos información del segundo argumento (archivo o directorio)
if (stat(argv[1], &atributos) == -1)
{
perror("Error en stat");
exit (-2);
}
if (!(atributos.st_mode & S_IFDIR))
{
fprintf(stdout, "El argumento %s no es un directorio \n", argv[1]);
exit(-3);
}
fprintf(stdout, "Directorio = %s \n", argv[1]);
strcpy(directorio,argv[1]);
signal(SIGCHLD,fin_hijo);
retorno=fork();
if (retorno ==0)
{
fd = open(LISTADO, O_CREAT| O_RDWR, 0600);
if (fd == -1)
{
fprintf(stderr,"Error al crear el fichero %s", LISTADO);
exit(-4);
}
obtener_entradas_directorio(argv[1],fd,1);
kill (getppid(),SIGUSR1);
}
else
{
signal(SIGUSR1,manejador);
pause();
}
return 0;
}
4
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
void obtener_entradas_directorio (char *directorio, int df, int tipo_entrada)
{
DIR *dirp;
struct dirent *direntp;
struct stat atributos;
int retorno;
char ruta[LONGITUD_MAX];
dirp = opendir (directorio);
if (dirp == NULL)
{
fprintf(stderr,"No se puede acceder al directorio %s\n", directorio);
exit (-5);
}
// Obtenemos la primera entrada del directorio (ED)
direntp = readdir(dirp);
if (dup2(df, STDOUT_FILENO)<0)
{
fprintf(stderr,"Error al redireccionar la salida al fichero %s\n", LISTADO);
exit(-6);
}
// Mientras haya entradas en el directorio
while (direntp != NULL)
{
// Construimos la ruta
sprintf(ruta, "%s/%s", directorio, direntp->d_name);
// Obtenemos información de la ED actual
retorno = stat(ruta, &atributos);
if (retorno == -1)
{
fprintf(stderr, "Error en stat de %s \n", direntp->d_name);
}
else
{
if (tipo_entrada==1)
{
// Si es un fichero regular, mostramos la ruta y el tamanno
if (atributos.st_mode & S_IFREG)
//
if (S_ISREG (atributos.st_mode) )
{
fprintf(stdout, "Ruta del archivo regular = %s Tamanno = %d bytes \n", ruta,
atributos.st_size);
}
}
// Si es un directorio seguimos por el subdirectorio siguiente
else if (tipo_entrada==2)
{
if (atributos.st_mode & S_IFDIR)
//
if (S_ISDIR (atributos.st_mode) )
{
fprintf(stdout, "Ruta del directorio = %s Tamanno = %d bytes \n", ruta,
atributos.st_size);
}
5
}
}
// Obtenemos la siguiente ED
direntp = readdir(dirp);
}
closedir(dirp);
close(df);
}
void manejador(int s)
{
fd = open(LISTADO, O_RDWR | O_APPEND);
if (fd == -1)
{
fprintf(stderr,"Error al abrir el fichero para annadir %s", LISTADO);
exit(-7);
}
obtener_entradas_directorio(directorio,fd,2);
}
void fin_hijo(int s)
{
wait(NULL);
fprintf (stdout, "El proceso hijo ha finalizado\n");
}
6
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
[Cuestión 3.]
Se desea implementar en C, haciendo uso de la librería de semáforos vista en clase, el funcionamiento de los
módulos operativos del Fotomatón 3000. El sistema se compone de los módulos de control de usuario, de control del flash y
el sistema de disparo que se implementarán en tres programas diferentes. Las relaciones entre los tres módulos son las
siguientes.
Cuando un usuario entre en el fotomatón un detector de presencia gestionado por el módulo de control se activará. El módulo
de control comunicará la situación al módulo de control de flash y al sistema de disparo. Una vez que la foto se tome el módulo
de control esperará la detección de la salida del usuario.
Cuando el sistema de control de flash reciba la notificación de que hay un usuario comenzará la carga de los condensadores y
cuando estén llenos avisará al módulo de disparo.
El módulo de disparo se activará cuando conozca que hay algún usuario, y esperará a que el flash esté cargado para comenzar
la detección de sonrisa. Cuando se detecte la sonrisa del usuario se tomará la foto y se imprimirá. Se avisará al módulo de
usuario que se ha concluido la operación.
Suponga que las siguientes funciones ya están implementadas:
• void detectar_entrada_usuario()
• void detectar_salida_usuario()
• void carga_condensadores()
• void detectar_sonrisa()
• void realizar_foto()
NOTAS
1. Cuando el propietario enciende la máquina se asegura que no hay nadie en su interior.
2. No se producen situaciones anómalas (no entran varias personas al mismo tiempo ni se van sin que se haga una foto).
3. Si el módulo de control de usuario recibiera una señal SIGTSTP se encargará de eliminar todos los semáforos creados
antes de salir.
/*************************************************************/
//
control.c
//
/*************************************************************/
#include "funciones.h"
int main()
{
Iniciador();
if (signal(SIGTSTP, Terminador)== SIG_ERR)
perror ("Error al instalar el manejador asociado a SIGTSTP");
while(1)
{
detectar_entrada_usuario();
Semaph_Up(usuflash);
Semaph_Up(usufoto);
Semaph_Down(foto);
detectar_salida_usuario();
}
}
/*************************************************************/
//
flash.c
//
/*************************************************************/
#include "funciones.h"
int main()
{
Iniciador();
while(1)
{
Semaph_Down(usuflash);
carga_condensadores();
7
Semaph_Up(flash);
}
}
/*************************************************************/
//
disparo.c
//
/*************************************************************/
#include "funciones.h"
int main()
{
Iniciador();
while(1)
{
Semaph_Down(usufoto);
Semaph_Down(flash);
detectar_sonrisa();
realizar_foto();
Semaph_Up(foto);
}
}
/*************************************************************/
//
funciones.h
//
/*************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include "libsem.h"
void Iniciador ();
void Terminador (int sig);
int usuflash, usufoto,flash,foto;
void detectar_entrada_usuario();
void detectar_salida_usuario();
void carga_condensadores();
void detectar_sonrisa();
void realizar_foto();
/*************************************************************/
//
funciones.c
//
/*************************************************************/
#include "funciones.h"
void Iniciador ()
{
usuflash = Semaph_Create("usuflash", 0);
usufoto = Semaph_Create("usufoto", 0);
flash = Semaph_Create("flash", 0);
foto = Semaph_Create("foto", 0);
if ((usuflash == -1) || (usufoto==-1) || (flash==-1) || (foto==-1))
{
perror("Error al crear semaforos.");
exit(-1);
}
}
void Terminador (int sig)
{
Semaph_Destroy("usuflash", usuflash);
8
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
Semaph_Destroy("usufoto", usufoto);
Semaph_Destroy("flash", flash);
Semaph_Destroy("foto", foto);
exit(0);
}
void detectar_entrada_usuario(){printf("Detectar entrada\n");};
void detectar_salida_usuario(){printf("Detectar salida\n");};
void carga_condensadores(){printf("Cargando flash\n");};
void detectar_sonrisa(){printf("Detectar sonrisa\n");};
}
9
10
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
[Cuestión 4.]
La futura versión del Fotomatón 4000 mantendrá el funcionamiento pero se implementará por medio de
comunicaciones por red entre módulos que podrán estar en diferentes localizaciones. El módulo de control de flash y el de
control de disparo realizarán tareas de servidor en los puertos 8000 y 9000 respectivamente.
1. El módulo de control de usuario realizará conexiones con los otros dos módulos. Una vez establecidas ambas
comunicaciones el módulo de control enviará un mensaje con la cadena "START" a ambos módulos.
2. Tras detectar la entrada de un usuario enviará la cadena "USUARIO" al módulo de control de flash. Este
lanzará la función de carga de flash y si retorna satisfactoriamente enviará la cadena "LISTO" al módulo de
control. En caso de que devuelva un error lo comunicará la módulo de control por medio del mensaje
“ERROR”.
3. Si el módulo de control recibe el mensaje "ERROR" en lugar de "LISTO" el servidor enviará la cadena
"RESET" a los módulos y éstos cerrarán los canales de comunicación abiertos antes de terminar.
4. Tras enviar la cadena “LISTO” el módulo de control de flash volverá al punto 2 y repetirá el ciclo hasta que se
reciba un “RESET”.
Implemente el programa correspondiente al módulo de control de flash realizado en el dominio de Internet. El servidor
aceptará comunicaciones en cualquiera de las direcciones del servidor en que se ejecute.
Suponga que está implementada la función
int carga_condensadores() que devuelve -1 si se produce un error en la carga y 0 si es satisfactoria
•
•
•
NOTAS:
Se garantiza que todos los intercambios de mensajes se completan con todos los mensajes indicados. No se reciben mensajes
Todas las comunicaciones tendrán un tamaño máximo de 256 bytes y podrán manipularse como cadenas de caracteres.
Pueden serle útiles las siguientes funciones
void *memset(void *s, int c, size_t n);
Copia el valor de c en cada uno de los primeros n caracteres en el objeto apuntado por s.
int strncmp(const char *s1, const char *s2, size_t n);
Compara no más de n caracteres de la cadena apuntada por s1 con la cadena apuntada por s2 y devuelve un entero mayor,
igual, o menor que cero, según la cadena apuntada por s1 es mayor, igual, o menor que la cadena apuntada por s2
Puntuación: 4 ptos.
Tiempo estimado:30 min.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define BUF_SIZE 256
main(){
/* Crear Sockets */
int dsf,dsfc; /* Descriptores socket */
if ((dsf = socket (AF_INET, SOCK_STREAM , 0 )) == -1){
perror("Creacion socket");
exit(EXIT_FAILURE);
}
/* Enlazarlos */
struct sockaddr_in addr,addr2;
int tamano = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
11
addr.sin_port = htons(8000);
addr.sin_addr.s_addr = INADDR_ANY;
if( bind(dsf, (struct sockaddr *) &addr, tamano) == -1){
perror("Enlace socket");
exit(EXIT_FAILURE);
}
/* Poner a la escucha*/
if( listen(dsf,1) == -1){
perror("Escucha socket");
exit(EXIT_FAILURE);
}
/* Acepto conexiones */
char buff[255];
dsfc=accept(dsf,(struct sockaddr *) &addr2, &tamano);
if ( dsfc == -1){
perror("Conexion socket");
exit(EXIT_FAILURE);
}
int final=0;
while(final!=1){
/* Leer de la conexión y almacenar en el buffer */
memset(buff,0,BUF_SIZE);
read(dsfc,buff,BUF_SIZE); /* LEE START o RESET */
if (strncmp(buff,"START",5)==0){ /* START */
/* Leer de la conexión y almacenar en el buffer */
memset(buff,0,BUF_SIZE);
read(dsfc,buff,BUF_SIZE); /* LEE USUARIO o RESET */
if (strncmp(buff,"USUARIO",7)==0){
if (carga_condensadores()==-1){
/* Comunica ERROR*/
write(dsfc,"ERROR",strlen("ERROR"));
memset(buff,0,BUF_SIZE);
read(dsfc,buff,BUF_SIZE); /* LEE RESET */
close(dsfc);
final==1;
}
else{
/* comunica LISTO*/
write(dsfc,"LISTO",strlen("LISTO"));
memset(buff,0,BUF_SIZE);
}
}
}
else{ /* RESET */
close(dsfc);
final==1;
}
}
close(dsf);
}
12
Tercera Convocatoria de Laboratorio de Sistemas
Operativos. Curso 2009/10. Tercero Ingeniería Informática
Nombre:
Apellidos:
C1
C2
C3
C4
NOTA
20-Dic.-2010 (9:00)
int carga_condensadores(){
printf("Flash cargado\n");
return(0);
}
13
Descargar