Autor: Adriano Scatena
-
process_manager_signals.c
2.1. Objetivo
2.2. Arquitectura del Diseño
2.3. Modelo de Ejecución
2.4. Comportamiento por Señal
2.5. Estructura de Datos Utilizada
2.6. Aspectos Técnicos Relevantes
2.7. Compilación -
shared_memory_ipc.c
3.1. Objetivo
3.2. Modelo General
3.3. Componentes IPC Utilizados
3.4. Cifrado Implementado
3.5. Control de Estado de Proceso
3.6. Terminación Coordinada
3.7. Compilación y Ejecución
Este repositorio implementa mecanismos avanzados de Comunicación entre Procesos (IPC) y control de concurrencia en sistemas GNU/Linux bajo estándar POSIX, utilizando lenguaje C a nivel de system calls.
El proyecto está compuesto por dos programas independientes:
process_manager_signals.cshared_memory_ipc.c
Ambos exploran problemas clásicos de Sistemas Operativos:
- Creación y jerarquía de procesos (
fork) - Reemplazo de imagen de proceso (
exec) - Manejo asincrónico de señales
- Sincronización entre procesos sin memoria compartida implícita
- Uso explícito de memoria compartida System V
- Comunicación mediante FIFOs
- Terminación coordinada y liberación segura de recursos
- Diseño robusto frente a condiciones de carrera
El enfoque del repositorio es práctico y técnico, orientado a demostrar comprensión profunda del modelo de ejecución de procesos en Linux.
Diseñar un proceso padre que responda dinámicamente a señales externas creando y gestionando procesos hijos con comportamientos diferenciados.
El programa implementa:
- Manejadores de señales livianos que solo modifican flags
volatile - Separación estricta entre:
- Código del manejador
- Lógica principal
- Uso de
pause()para bloqueo eficiente - Lista enlazada dinámica tipo LIFO para registrar PIDs
Se evita ejecutar lógica compleja dentro de los handlers, reduciendo comportamiento indefinido.
El proceso padre:
- Registra manejadores para
SIGUSR1,SIGUSR2ySIGTERM - Permanece bloqueado esperando señales
- Reacciona según la señal recibida
- Ejecuta
fork() - Registra el PID en una lista enlazada dinámica
- El hijo:
- Configura
SIGALRM - Imprime su PID y el del padre cada 5 segundos
- Utiliza
alarm(5)para temporización periódica
- Configura
Se implementa una bandera _5seg para desacoplar la señal de la lógica de impresión.
- Ejecuta
fork() - El hijo reemplaza su imagen con:
execl("/bin/ls", "ls", NULL);Esto demuestra uso correcto de exec y reemplazo total del espacio de memoria del proceso.
- Recorre la lista dinámica de hijos creados por
SIGUSR1 - Envía
SIGTERMa cada uno con intervalo de 1 segundo - Libera memoria dinámica
- Finaliza ordenadamente
typedef struct nodo {
pid_t pid;
struct nodo *siguiente;
} nodo;Permite:
- Registro incremental
- Eliminación ordenada
- Gestión explícita de memoria (
malloc/free)
- Uso de
volatile boolpara flags de señal - Separación de handlers y lógica
- Uso correcto de
SIG_DFLen procesos hijos - Gestión manual de memoria dinámica
- Prevención de ejecución simultánea indebida
gcc process_manager_signals.c -o process_managerImplementar comunicación coordinada entre dos procesos independientes (A y B) utilizando:
- Memoria compartida System V
- Pipes nombrados (FIFO)
- Señales POSIX
- Cifrado modular aplicado a los datos
El sistema implementa un protocolo de alternancia estricta:
- A escribe posiciones 0–9
- B escribe posiciones 10–19
- Ninguno puede escribir hasta que el otro haya leído
- Escritura: 1 valor por segundo
- Lectura: sincronizada por señales
- Finalización coordinada mediante
SIGTERM
Funciones utilizadas:
ftokshmgetshmatshmdtshmctl
Estructura:
typedef struct {
int datos[20];
} shared_memory;La memoria solo contiene datos, nunca flags de control.
pipe_fifoApipe_fifoB
Se utilizan exclusivamente para intercambio inicial de PIDs.
Se implementa manejo robusto ante:
EEXISTENXIO- Apertura no bloqueante
Se emplean:
SIGUSR1SIGUSR2SIGTERM
Las señales activan flags volatile sig_atomic_t, garantizando:
- Seguridad en acceso concurrente
- No ejecución de lógica compleja dentro del handler
- Separación entre señal y decisión
Función pública:
[ f(x) = (4x + 5) \mod 27 ]
Función inversa:
[ f^{-1}(x) = (7x + 19) \mod 27 ]
Cada proceso:
- Cifra antes de escribir
- Descifra al leer
Esto introduce una capa adicional de transformación de datos sobre IPC.
Se implementa:
kill(pid, 0)Para verificar existencia del proceso remoto antes de finalizar.
Esto evita zombies y asegura terminación limpia.
Proceso A:
- Envía
SIGTERMa B - Espera confirmación de muerte
- Libera memoria compartida
- Elimina FIFOs
Proceso B:
- Se desasocia
- Elimina su FIFO
- Finaliza
Se garantiza:
- No fuga de memoria
- No recursos IPC huérfanos
- No procesos zombies
gcc shared_memory_ipc.c -o shared_memory_ipc -lrtTerminal 1:
./shared_memory_ipc ATerminal 2:
./shared_memory_ipc BFinalización:
kill -SIGTERM <PID_de_A>- Uso de
volatile sig_atomic_ten vez de tipos primitivos simples - Separación estricta entre datos y control
- No utilización de busy waiting
- Uso de
pause()para espera eficiente - Manejo explícito de errores (
errno) - Liberación manual de recursos IPC
- Implementación de protocolo de alternancia sin mutexes
- C (GNU)
- POSIX Signals
- System V Shared Memory
- FIFOs
- fork / exec
- alarm
- kill
- IPC
- Concurrencia sin threads
- Sincronización asincrónica
Este repositorio demuestra dominio en programación de sistemas, diseño concurrente y gestión explícita de recursos a bajo nivel en entornos Linux.