¿Qué es un proceso?
Un proceso es un programa en ejecución. Los procesadores comparten tiempo con todos los procesos cargados en memoria RAM. Cuando un programa cede la CPU, se guarda una instantánea llamada BCP (Bloque de Control de Procesos) que almacena el estado del programa para poder retomarlo más adelante.
Estados de un proceso
- Ejecución: el proceso está usando la CPU.
- Listo: cargado en RAM, esperando turno en la CPU.
- Bloqueado: esperando recursos que otra aplicación está usando.
La contienda es la competencia entre procesos por acceder a la CPU. Existen distintos métodos de asignación: Round-Robin, por prioridades, por tiempos estimados de ejecución, etc.
Visualización de procesos
En Windows podemos ver los procesos activos con el Administrador de Tareas o con el comando tasklist en CMD, que también muestra el PID de cada proceso.
En Linux/Ubuntu, usamos el comando ps o ps -f para incluir también el PPID (identificador del proceso padre).
Funciones en C para trabajar con procesos
execl()
Ejecuta comandos del sistema o programas externos. Si falla, devuelve -1. El código que haya a continuación de execl() solo se ejecuta si hay error, porque si tiene éxito el proceso actual es reemplazado por el nuevo.
#include <stdio.h>
#include <unistd.h>
void main(){
printf("Los archivos del directorio son: \n");
execl("/bin/ls", "ls", "-l", (char *)NULL);
printf("ERROR!!!");
}

system()
Ejecuta comandos del sistema. A diferencia de execl(), el proceso actual no se reemplaza y la ejecución continúa tras el comando. Permite redirigir la salida a un fichero.
#include <stdio.h>
#include <stdlib.h>
void main(){
system("ls -l > ficSalida");
printf("FIN");
}

getpid() y getppid()
getpid(): devuelve el PID (identificador) del proceso actual.getppid(): devuelve el PID del proceso padre.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(){
pid_t id_pactual, id_padre;
id_pactual = getpid();
id_padre = getppid();
printf("PID actual: %d \n", id_pactual);
printf("PID padre: %d \n", id_padre);
}

fork()
Crea un proceso hijo. Devuelve 0 en el proceso hijo y el PID del hijo en el proceso padre. Si devuelve -1, ha ocurrido un error.
wait()
Pausa el proceso padre hasta que el proceso hijo finalice.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(){
pid_t pid, hijo_pid;
pid = fork();
if (pid == -1){
printf("Ha habido un error");
exit(-1);
}
if(pid == 0){
printf("soy el proceso hijo \n\t Mi PID es %d. El PID de mi padre es: %d. \n", getpid(), getppid());
}
else{
hijo_pid = wait(NULL);
printf("Soy el proceso padre: \n\t Mi PID es %d. El PID de mi padre es: %d. \n\t Mi hijo %d terminó. \n", getpid(), getppid(), pid);
}
}

Ejercicio
Crear un programa en el que un proceso padre genere un proceso hijo. La variable n tiene el valor 7. El proceso hijo suma 5 a n y el proceso padre resta 5 a n. Ambos muestran el resultado junto con su PID y PPID.
Solución
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(){
pid_t pid, hijo;
int n = 7;
pid = fork();
if (pid == -1){
printf("Error \n");
exit(-1);
}
if (pid == 0){
n = n + 5;
printf("Soy el hijo. Valor de n = %d.\n Proceso %d, padre %d \n\n", n, getpid(), getppid());
}
else{
n = n - 5;
printf("Soy el padre. Valor de n = %i.\n Proceso %d, padre %d \n\n", n, getpid(), getppid());
}
}

