Bloqueo de procesos, planificación de la CPU y gestión de memoria en sistemas operativos
Bloqueo de procesos y bloque de control de proceso
Bloqueo de procesos y bloque de control de proceso: cuando se ejecuta más de un proceso de manera concurrente en un sistema, ambos necesitan que el sistema les suministre una serie de recursos. Para ello, el propio sistema operativo se encarga de asignar estos recursos en un orden adecuado y atendiendo a unas prioridades.
Cada vez que un programa se convierte en proceso, es decir, cada vez que se ejecuta, además de ubicarse en memoria las instrucciones que permiten su ejecución y el procesamiento de datos que pueda utilizar, se le asocia una estructura de datos. Esta estructura de datos, que es única para cada proceso, identifica el proceso respecto a los demás y permite controlar su correcta ejecución. A esta estructura de datos se la denomina bloque de control de proceso.
El bloque de control de proceso contiene:
- Estado actual del proceso: un proceso puede estar en ejecución, detenido o bloqueado. El estado de bloqueado es el más conflictivo, ya que los bloqueos pueden provocar que otros procesos también dejen de funcionar, especialmente si el bloqueo es provocado por un componente hardware y varios procesos utilizan el mismo componente.
- Identificador del proceso: a cada proceso, y dependiendo del sistema operativo, se le asigna un PID o código de identificador de proceso. Este código normalmente es un número que el propio sistema operativo asigna según unas prioridades y unos parámetros de diseño preestablecidos, teniendo en cuenta el uso y funcionalidad de cada proceso.
- Prioridad del proceso: la prioridad de cada proceso se asigna de forma automática por parte del sistema operativo. La prioridad de los procesos puede ser modificada por los usuarios que tengan privilegios para ello (normalmente el dueño del propio proceso puede modificar su prioridad y el administrador del sistema podrá modificar la prioridad del proceso que corresponda a cualquier usuario).
- Ubicación de memoria: teniendo en cuenta la técnica utilizada para ubicar los programas en memoria y dependiendo del tipo de programa que se trate, el sistema operativo tendrá que ubicar cada proceso en una zona independiente de memoria.
- Recursos utilizados: cada proceso debe tener a su disposición determinados recursos hardware y algunos recursos software para poder ejecutarse. Estos recursos se pondrán a disposición del proceso en el mismo momento en que comienza a ejecutarse. Como es habitual, la asignación de estos recursos la realizará el sistema operativo.
Paso de programa a proceso
Cuando un programa pasa a ser un proceso: cuando hacemos doble clic o escribimos el nombre de un fichero ejecutable, se carga en memoria un proceso del propio sistema operativo denominado cargador. Este proceso lleva el programa para iniciar su ejecución realizando las siguientes funciones:
- Crear el bloque de control de proceso: se le asigna un identificador (PID), una prioridad base, así como todos los recursos necesarios excepto la CPU.
- Se inserta en la tabla de procesos del sistema.
- Se carga en memoria virtual (según la técnica de gestión de memoria utilizada).
- Cuando ya tiene todos los recursos asignados (menos la CPU), el campo de estado del proceso del bloque de control de procesos se cambia a preparado y se inserta en la cola de procesos preparados para ser ejecutados por la CPU.
El proceso del sistema que controla la cola de la CPU recibe el nombre de planificador y es el encargado de decidir, según las prioridades, qué proceso será el siguiente que ejecutará la CPU. Los pasos que tiene que dar el planificador son los siguientes:
- Asignar nuevas prioridades a los procesos en la cola de la CPU.
- Elegir el proceso con la prioridad más alta.
- Cambiar el campo de estado del proceso elegido a ejecución.
- Llamar a la rutina de cambio de contexto que cargará el proceso en la CPU, es decir, copiará el estado hardware en los registros de la CPU, donde el último registro a actualizar será el registro o contador de programa para que la próxima instrucción a ejecutar sea la siguiente donde se quedó el proceso.
En general, la mayoría de los ordenadores tienen un único procesador. Esto implica que, cuando se están realizando varias tareas a la vez, es necesario compartir el tiempo de trabajo de la CPU. El tiempo compartido resulta de dividir el tiempo de ejecución del procesador en breves intervalos de tiempo (quantum) e ir asignando cada uno de estos intervalos de ejecución a cada proceso que se esté ejecutando. Así, los ciclos de la CPU, sincronizados por el reloj del sistema, se irán asignando a los distintos procesos. Toda la información referente a esta planificación se almacena en la tabla de procesos que contiene el bloque de control de procesos.
Cuando un proceso solicita una operación de entrada-salida, su estado cambia a pausado y se coloca en la cola de dispositivo de entrada-salida que desea utilizar. Una vez finalizada la operación de entrada-salida, vuelve a cambiar su estado a preparado y se introduce en la cola de la CPU. Finalizada la operación correspondiente, la CPU cambiará el estado del proceso a zombie, que es aquel que ha acabado de ejecutarse pero le faltan por liberar algunos recursos, por lo que el proceso puede considerarse todavía vivo dentro del sistema.
Hebras y multihebra (conceptos)
Hebras y multihebra (conceptos): una hebra o subproceso es un punto de ejecución de un proceso. Un proceso siempre tendrá como mínimo una hebra en la que se ejecuta el propio programa, ya que estas representan un método software que permite mejorar el rendimiento y eficacia de los sistemas operativos. Esto lo logra reduciendo la sobrecarga por el cambio de contexto entre procesos; es decir, las hebras asumirán el papel de los procesos como unidad de planificación, donde un proceso será la unidad propietaria de recursos para una serie de hebras.
Todos los recursos excepto la CPU son gestionados por el proceso. El proceso es el propietario de la memoria que necesita, del hardware, de los ficheros, etc. Los tiempos de la CPU son gestionados y asignados a los diferentes hilos de un proceso; es decir, cuando uno se está ejecutando, el resto de los hilos estarán en espera, bloqueados, etc. La gestión es del propio proceso, no de los hilos. De esta forma, la comunicación entre las diferentes hebras del proceso comparten el mismo espacio de memoria.
Estados, prioridades y planificador de procesos
Estados, prioridades y planificador de procesos: los estados son 3:
- Estado en ejecución: se da cuando el procesador está ejecutando instrucciones de un proceso en un instante determinado.
- Estado preparado, en espera o activo: en este caso, el proceso está preparado para ejecutarse; es decir, espera turno para poder utilizar su intervalo de tiempo de la CPU.
- Estado bloqueado: en este caso el proceso está detenido. Está bloqueado por alguna razón, que puede ser que dos procesos utilicen el mismo fichero de datos o que dos procesos necesiten utilizar la misma unidad lectora de CD o memoria, etc.
Algoritmos de planificación
Algoritmos de planificación: estos algoritmos se diseñan dependiendo de su función y pueden ser de distintos tipos:
- Expropiación: el planificador de la CPU puede intervenir cuando un proceso pasa voluntariamente a estado de espera, ya que necesita realizar una operación de entrada-salida, o se tienen que sincronizar con otro proceso para utilizar espacios comunes, normalmente de memoria. También puede intervenir cuando finaliza un proceso, aunque en este caso lo llamamos sin expropiación.
- Intervalos de tiempo: el proceso recibe atención de la CPU durante un intervalo de tiempo.
- Prioridades: a los procesos se les pueden asignar prioridades estáticas o dinámicas. En este caso suele ser habitual, incluso necesaria, la intervención del usuario o administrador del sistema.
- Tiempos límites: existe el tiempo límite para que termine un determinado proceso; es decir, cuanto más cerca esté de su límite, se vuelve más urgente y se le asignan más ciclos consecutivos de CPU.
Ejemplos concretos de algoritmos:
- Algoritmo de operación por rondas (Round Robin): la asignación de tiempos de ejecución a los distintos procesos es la misma y se realiza de forma secuencial; es decir, a cada proceso se le asigna el mismo quantum de tiempo y la selección de entre los procesos se realiza mediante una cola FIFO (primero en entrar y luego salir). Cuando llega un proceso nuevo y hay otro en ejecución, los ciclos de CPU se distribuyen entre ellos, o ejecutándose antes un ciclo de CPU para el proceso que está activo y no para el recién llegado, al que se le asignará su ciclo inmediatamente después.
- Algoritmo FCFS (First Come, First Served): primero en entrar, primero en ser servido. Los ciclos de CPU de cada proceso se asignan en función de una cola FIFO, aunque en este caso se les asignan tiempos o ciclos de CPU hasta que termina completamente. A continuación se ejecuta completo el siguiente proceso que hay en la cola FIFO y así sucesivamente hasta finalizar la ejecución del último proceso.
- SJF (Shortest Job First): (siglas: el resto del tiempo más corto) permite asignar tiempo de ejecución de forma prioritaria a procesos muy cortos para ejecutarlos en el menor tiempo posible. Si se está ejecutando un proceso y llega otro, independientemente de la duración del nuevo, el proceso que está en ejecución finalizará, y una vez finalizado, el siguiente proceso a consumir ciclos de CPU será el más corto de los que haya en la cola de espera.
- SRTF (Shortest Remaining Time First): (el primero del tiempo restante más breve) variante de SJF. En este caso, la asignación de ciclos de la CPU se hace en función del proceso al que le quedan menos ciclos para terminar. De esta forma, cuando llega un proceso nuevo se estiman los ciclos que les quedan tanto al proceso que está en ejecución como al que ha llegado, y de los que hay en ese momento en la cola de procesos a ejecutar, se terminará aquel al que le quedan menos ciclos para su finalización, y así sucesivamente hasta terminar con todos los procesos planificados.
Memoria virtual
Memoria virtual: previamente a esto, había una técnica que era dividir el programa en partes llamadas capas. Cada una de estas capas se iría ejecutando según fuera necesario, es decir, del disco duro a la memoria. Cuando fuera necesario utilizar otra parte del programa que no estuviera en memoria principal, se accedería de nuevo al disco para cargar la siguiente capa en memoria principal. El método conocido como memoria virtual, diseñado por Fotheringham, consideró que el programa que se iba a ubicar en memoria podría ser excesivamente grande para el tamaño físico de esta. Por tanto, permanecería en memoria la parte del programa que se está ejecutando, mientras que el resto seguiría ubicada en el disco; es decir, esta técnica considera el espacio en disco libre como si se tratase de memoria RAM. Si en un momento determinado es necesario utilizar una parte del programa almacenado en un disco duro como memoria virtual, pasará a memoria RAM para su ejecución, y la parte del programa que estaba en memoria RAM se almacenará en el disco duro.
Intercambio de memoria o swapping
Intercambio de memoria o swapping: es una técnica parecida a la memoria virtual. Según el estado en el que se encuentre el proceso de cada usuario, la memoria tiene que liberar su proceso pasándolo a lo que llamamos zona de intercambio mediante la técnica llamada