Asignatura de Sistemas Operativos, 2º curso del Grado en Ingeniería Informática de la Universidad de Granada (UGR)
Llamadas al sistema para el Sistema de Archivos (parte 1).
Llamadas al sistema para el Sistema de Archivos (Parte 2)
Llamadas al sistema para el Control de Procesos
Comunicación entre procesos utilizando cauces
Ejercicio 1 - consumidorFIFO.c & productorFIFO.c
En primer lugar hay que ejecutar el consumidor
, que creará un archivo FIFO (ComunicacionFIFO) y quedará a la espera de recibir un mensaje del productor
. A continuación, en otro terminal, habrá que ejecutar el productor
con un único argumento, que será un mensaje; dicho mensaje aparecerá en el terminal del consumidor
. Para terminar la ejecución el productor
tendrá que enviar como argumento el mensaje fin.
Ejercicio 2 - tarea6.c
pipe(fd)
crea un cauce sin nombre; al pasarle fd
como parámetro se asigna por defecto el modo lectura a fd[0] y el modo escritura a fd[1].
Con la orden fork
se crea un proceso hijo, el cual cierra el descriptor de lectura fd[0] y posteriormente escribe un mensaje a través del cauce en el descriptor de escritura fd[1].
El proceso padre cierra el descriptor de escritura fd[1] y lee del cauce lo que ha escrito el hijo con el descriptor de lectura fd[0], imprimiendo por pantalla dicho mensaje y el número de bytes que ocupa.
Ejercicio 3 - tarea7.c
Programa ilustrativo del uso de pipes y la redirección de entrada y salida estándar simulando la orden: ls | sort
.
Ejercicio 4 - tarea8.c
La ejecución de este programa realiza la misma acción que en el ejercicio anterior, ls | sort
, pero en lugar de realizar primero el cierre del descriptor de archivo close(fd)
y después la duplicación del descriptor dup(fd)
, ambas órdenes se combinan en una sola: dup2(int oldfd, int newfd);
Ejercicio 5 - maestro_ej5.c & esclavo_ej5.c
Cálculo de números primos en un intervalo utilizando cauces sin nombre.
Llamadas al sistema para gestión y control de señales
tarea9.c
Este programa ignora las interrupciones por teclado Ctrl+C
. Para poder interrumpirlo habría que, por ejemplo, ejecutar la orden kill -9 <PID>
desde otro terminal (se puede consultar el <PID> con la orden top
).
tarea10.c
El programa establece un manejador para las señales recibidas (interrupciones de teclado Ctrl+C
), finalizando cuando recibe tres.
Ejercicio 1 - envioSignal.c & reciboSignal.c
En primer lugar hay que ejecutar reciboSignal
para que quede a la espera de recibir una señal en segundo plano. Después, ejecutar envioSignal [012] <PID>
, donde <PID> es el identificador de proceso de reciboSignal
, el cual se puede consultar con la orden top
. Según la orden enviada (0, 1 ó 2), terminará el proceso o se mostrará un mensaje u otro en el terminal donde se ejecuta reciboSignal
; los mensajes mostrados por 1 y 2 se pueden configurar en en la función static void sig_USR_hdlr(int sigNum)
de reciboSignal
.
El funcionamiento de cada sección del código se especifica en los comentarios del mismo.
Ejercicio 2 - contador.c
Maneja cualquier señal recibida y muestra cuántas veces ha recibido dicha señal.
Ejercicio 3
Suspende la ejecución del proceso actual hasta que se reciba la señal SIGUSR1. Para comprobar su correcto funcionamiento ejecutar ./ejercicio3 &
y una vez obtenido su PID, ejecutar el programa envioSignal del Ejercicio 1 para enviar la señal SIGUSR1: ./envioSignal 1 <PID ejercicio3>
.
Ejercicio 4 - tarea12.c
El programa crea una máscara donde sólo se añade la señal SIGTERM. Aplica la máscara y con ello bloquea la señal SIGTERM. Duerme durante 10 segundos y si durante este tiempo recibe dicha señal, no reaccionará porque está bloqueada; Una vez termina de "dormir", desbloquea la señal SIGTERM, reanudando la máscara antigua y comprobando si la variable signal_recibida está activada, lo cual quiere decir que ha recibido la señal SIGTERM mientras dormía, en cuyo caso mostrará un mensaje indicándolo; si no, no mostrará nada.
Al igual que en el ejercicio anterior se puede enviar SIGTERM ejecutando ./tarea12 &
para obtener su PID y ./envioSignal 0 <PID tarea12>
para enviar la señal SIGTERM.
Control de archivos y archivos proyectados en memoria
Ejercicio 1
Crear un archivo de texto con varias líneas con texto de prueba y ejecutar ./ejercicio1 sort "<" prueba.txt
.
Ejercicio 2
Ejecutar ./ejercicio2 ls "|" sort
.
Ejercicio 3
Con el mismo archivo de texto del Ejercicio 1 ejecutar el mismo programa ejercicio3
en dos terminales distintos con la misma orden: ./ejercicio3 prueba.txt
. Esto hará que se bloquee el acceso al archivo desde el primer proceso lanzado y hasta que no se desbloquee en uno no aparecerá por pantalla en el otro terminal la línea "Procesando el archivo prueba.txt".
Ejercicio 4
Ejecutar ./ejercicio4 bloq_ej4
, donde el primer argumento bloq_ej4 será el nombre del archivo, que no tiene porqué existir previamente. En otro terminal ejecutar el mismo comando para comprobar que no se puede ejecutar otra instancia al estar el cerrojo establecido en la primera ejecución.
Ejercicio 5
La ejecución de este programa ./ejercicio5 <arch_orig> <arch_destino>
supone lo mismo que realizar en Linux la orden cp <arch_orig> <arch_destino>
. El archivo de destino lo crea el programa si no existe.