Procesos
Un proceso no es más que una instancia de un programa en ejecución, incluyendo los
valores actuales del contador de programa, los registros y las variables.
En concepto, cada proceso tiene su propia CPU virtual; en la realidad, la CPU real
conmuta de un proceso a otro, pero para entender el sistema es mucho más fácil pensar
en una colección de procesos que se ejecutan en (pseudo) paralelo, en vez de tratar de
llevar la cuenta de cómo la CPU conmuta de programa en programa. Esta conmutación
rápida de un proceso a otro se conoce como multiprogramación.
Desde luego que sólo hay un contador de programa físico, por lo que cuando se
ejecuta cada proceso, se carga su contador de programa lógico en el contador de
programa real. Cuando termina (por el tiempo que tenga asignado), el contador de
programa físico se guarda en el contador de programa lógico almacenado, del proceso en
memoria.
La idea clave es que un proceso es una actividad de cierto tipo: tiene un programa, una
entrada, una salida y un estado. Varios procesos pueden compartir un solo procesador
mediante el uso de un algoritmo de planificación para determinar cuándo se debe detener
el trabajo en un proceso para dar servicio a otro.
Creación de un proceso
Los sistemas operativos necesitan cierta manera de crear procesos. En sistemas muy
simples o sistemas diseñados para ejecutar sólo una aplicación (por ejemplo, el
controlador en un horno de microondas), es posible tener presentes todos los procesos
que se vayan a requerir cuando el sistema inicie. No obstante, en los sistemas de
propósito general se necesita cierta forma de crear y terminar procesos según sea
necesario durante la operación.
Ahora analizaremos varias de estas cuestiones. Hay cuatro eventos principales que
provocan la creación de procesos: 1. El arranque del sistema. 2. La ejecución, desde un
proceso, de una llamada al sistema para creación de procesos. 3. Una petición de usuario
para crear un proceso. 4. El inicio de un trabajo por lotes.
Generalmente, cuando se arranca un sistema operativo se crean varios procesos.
Algunos de ellos son procesos en primer plano; es decir, procesos que interactúan con los
usuarios (humanos) y realizan trabajo para ellos. Otros son procesos en segundo plano,
que no están asociados con usuarios específicos sino con una función específica. Los
procesos que permanecen en segundo plano para manejar ciertas actividades como
correo electrónico, páginas Web, noticias, impresiones, etcétera, se conocen como
demonios (daemons).
Técnicamente, en todos estos casos, para crear un proceso hay que hacer que un
proceso existente ejecute una llamada al sistema de creación de proceso. Ese proceso
puede ser un proceso de usuario en ejecución, un proceso del sistema invocado mediante
el teclado o ratón, o un proceso del administrador de procesamiento por lotes. Lo que
hace en todo caso es ejecutar una llamada al sistema para crear el proceso. Esta llamada
al sistema indica al sistema operativo que cree un proceso y le indica, directa o indirec-
tamente, cuál programa debe ejecutarlo.
Terminación de un proceso
Una vez que se crea un proceso, empieza a ejecutarse y realiza el trabajo al que está
destinado. Sin embargo, nada dura para siempre, ni siquiera los procesos. Tarde o
temprano el nuevo proceso terminará, por lo general debido a una de las siguientes
condiciones:
1. Salida normal (voluntaria).
2. Salida por error (voluntaria).
3. Error fatal (involuntaria).
4. Eliminado por otro proceso (involuntaria).
La mayoría de los procesos terminan debido a que han concluido su trabajo. Cuando
un compilador ha compilado el programa que recibe, ejecuta una llamada al sistema para
indicar al sistema operativo que ha terminado.
La segunda razón de terminación es que el proceso descubra un error. Ej Los procesos
interactivos orientados a pantalla por lo general no terminan cuando reciben parámetros
incorrectos.
La tercera razón de terminación es un error fatal producido por el proceso, a menudo
debido aun error en el programa. Algunos ejemplos incluyen el ejecutar una instrucción
ilegal, hacer referencia a una parte de memoria no existente o la división entre cero.
La cuarta razón por la que un proceso podría terminar es que ejecute una llamada al
sistema que indique al sistema operativo que elimine otros procesos. En UNIX esta
llamada es kill . La función correspondiente en Win32 es TerminateProcess . En ambos
casos, el proceso eliminador debe tener la autorización necesaria para realizar la
eliminación.
Jerarquías de procesos
En algunos sistemas, cuando un proceso crea otro, el proceso padre y el proceso hijo
continúan asociados en ciertas formas. El proceso hijo puede crear por sí mismo más
procesos, formando una jerarquía de procesos. Observe que, a diferencia de las plantas y
los animales que utilizan la reproducción sexual, un proceso sólo tiene un padre (pero
cero, uno, dos o más hijos).
En UNIX, un proceso y todos sus hijos, junto con sus posteriores descendientes,
forman un grupo de procesos. Cuando un usuario envía una señal del teclado, ésta se
envía a todos los miembros del grupo de procesos actualmente asociado con el teclado
(por lo general, todos los procesos activos que se crearon en la ventana actual). De
manera individual, cada proceso puede atrapar la señal, ignorarla o tomar la acción
predeterminada que es ser eliminado por la señal.
En contraste, Windows no tiene un concepto de una jerarquía de procesos. Todos los
procesos son iguales. La única sugerencia de una jerarquía de procesos es que, cuando
se crea un proceso, el padre recibe un indicador especial un token (llamado manejador)
que puede utilizar para controlar al hijo. Sin embargo, tiene la libertad de pasar este
indicador a otros procesos, con lo cual invalida la jerarquía. Los procesos en UNIX no
pueden desheredar a sus hijos.
Estados de un proceso
Aunque cada proceso es una entidad independiente, con su propio contador de
programa y estado interno, a menudo los procesos necesitan interactuar con otros. Un
proceso puede generar cierta salida que otro proceso utiliza como entrada.
Cuando un proceso se bloquea, lo hace debido a que por lógica no puede continuar,
comúnmente porque está esperando una entrada que todavía no está disponible. También
es posible que un proceso, que esté listo en concepto y pueda ejecutarse, se detenga
debido a que el sistema operativo ha decidido asignar la CPU a otro proceso por cierto
tiempo. Estas dos condiciones son completamente distintas. En el primer caso, la
suspensión está inherente en el problema, en el segundo caso, es un tecnicismo del
sistema.
Los tres estados en los que se puede encontrar un proceso:
1. En ejecución (en realidad está usando la CPU en ese instante).
2. Listo (ejecutable; se detuvo temporalmente para dejar que se ejecute otro proceso).
3. Bloqueado (no puede ejecutarse sino hasta que ocurra cierto evento externo).
En sentido lógico, los primeros dos estados son similares. En ambos casos el proceso
está deseoso de ejecutarse; sólo en el segundo no hay temporalmente una CPU para él.
El tercer estado es distinto de los primeros dos en cuanto a que el proceso no se puede
ejecutar, incluso aunque la CPU no tenga nada que hacer.
La transición 1 ocurre cuando el sistema operativo descubre que un proceso no puede
continuar justo en ese momento.
Las transiciones 2 y 3 son producidas por el planificador de procesos, una parte del
sistema
operativo, sin que el proceso sepa siquiera acerca de ellas. La transición 2 ocurre cuando
el planificador decide que el proceso en ejecución se ha ejecutado el tiempo suficiente y
es momento de dejar que otro proceso tenga una parte del tiempo de la CPU. La
transición 3 ocurre cuando todos los demás procesos han tenido su parte del tiempo de la
CPU y es momento de que el primer proceso obtenga la CPU para ejecutarse de nuevo.
La transición 4 ocurre cuando se produce el evento externo por el que un proceso
estaba esperando (como la llegada de ciertos datos de entrada). Si no hay otro proceso
en ejecución en ese instante, se activa la transición 3 y el proceso empieza a ejecutarse.
En caso contrario, tal vez tenga que esperar en el estado listo por unos instantes, hasta
que la CPU esté disponible y sea su turno deutilizarla.
Implementación de los procesos
Para implementar el modelo de procesos, el sistema operativo mantiene una tabla (un
arreglo de estructuras) llamada tabla de procesos, con sólo una entrada por cada proceso
(algunos autores llaman a estas entradas bloques de control de procesos). Esta entrada
contiene información importante acerca del estado del proceso, incluyendo su contador de
programa, apuntador de pila, asignación de memoria, estado de sus archivos abiertos,
información de contabilidad y planifcación, y todo lo demás que debe guardarse acerca
del proceso cuando éste cambia del estado en ejecución a listo o bloqueado, de manera
que se pueda reiniciar posteriormente como si nunca se hubiera detenido.
La figura 2-4 muestra algunos de los campos clave en un sistema típico. Los campos
en la primera columna se relacionan con la administración de procesos; los otros dos se
relacionan con la administración de memoria y archivos, respectivamente. Hay que
recalcar que los campos contenidos en la tabla de procesos varían de un sistema a otro,
pero esta figura nos da una idea general de los tipos de información necesaria.
PLANIFICACIÓN
Cuando una computadora se multiprograma, con frecuencia tiene varios procesos o
hilos que compiten por la CPU al mismo tiempo. Esta situación ocurre cada vez que dos o
más de estos procesos se encuentran al mismo tiempo en el estado listo. Si sólo hay una
CPU disponible, hay que decidir cuál proceso se va a ejecutar a continuación. La parte del
sistema operativo que realiza esa decisión se conoce como planificador de procesos y el
algoritmo que utiliza se conoce como algoritmo de planificación.
Los algoritmos de planificación se pueden dividir en dos categorías con respecto a la
forma en que manejan las interrupciones del reloj. Un algoritmo de programación no
apropiativo (nonpreemptive) selecciona un proceso para ejecutarlo y después sólo deja
que se ejecute hasta que el mismo se bloquea (ya sea en espera de una operación de
E/S o de algún otro proceso) o hasta que libera la CPU en forma voluntaria.
Por el contrario, un algoritmo de planificación apropiativa selecciona un proceso y deja
que se ejecute por un máximo de tiempo fijo. Si sigue en ejecución al final del intervalo de
tiempo, se suspende y el planificador selecciona otro proceso para ejecutarlo (si hay uno
disponible). Para llevar a cabo la planificación apropiativa, es necesario que ocurra una
interrupción de reloj al final del intervalo de tiempo para que la CPU regrese el control al
planificador.
Metas de los algoritmos de planificación
Para poder diseñar un algoritmo de programación, es necesario tener cierta idea de lo
que debe hacer un buen algoritmo. Algunos objetivos dependen del entorno
(procesamiento por lotes, interactivo o de tiempo real), pero hay también algunos otros
que son deseables en todos los casos.
Todos los sistemas
Equidad - Otorgar a cada proceso una parte justa de la CPU
Aplicación de políticas - Verificar que se lleven a cabo las políticas establecidas
Balance - Mantener ocupadas todas las partes del sistema
Sistemas de procesamiento por lotes
Rendimiento - Maximizar el número de trabajos por hora
Tiempo de retorno - Minimizar el tiempo entre la entrega y la terminación
Utilización de la CPU - Mantener ocupada la CPU todo el tiempo
Sistemas interactivos
Tiempo de respuesta - Responder a las peticiones con rapidez
Proporcionalidad - Cumplir las expectativas de los usuarios
Sistemas de tiempo real
Cumplir con los plazos - Evitar perder datos
Algortimos
Primero en entrar, primero en ser atendido
Probablemente el más simple de todos los algoritmos de planificación es el de tipo
primero en entrar, primero en ser atendido (FCFS, First-Come, First-Served) no
apropiativo. Con este algoritmo, la CPU se asigna a los procesos en el orden en el que la
solicitan. En esencia hay una sola cola de procesos listos. Cuando el primer trabajo entra
al sistema desde, se inicia de inmediato y se le permite ejecutarse todo el tiempo que
desee. No se interrumpe debido a que se ha ejecutado demasiado tiempo. A medida que
van entrando otros trabajos, se colocan al final de la cola. Si el proceso en ejecución se
bloquea, el primer proceso en la cola se ejecuta a continuación. Cuando un proceso
bloqueado pasa al estado listo, al igual que un trabajo recién llegado, se coloca al final de
la cola.
La gran fuerza de este algoritmo es que es fácil de comprender e igualmente sencillo de
programar y es equitativo. Su desventaja es si un proceso con mucho tiempo de ejecución
o acciones de lectura y/o escritura generara mucho tiempo de espera a los demás
procesos que están en la cola de listos.
El trabajo más corto primero
Suponiendo que los tiempos de ejecución se conocen de antemano. Cuando hay varios
trabajos de igual importancia esperando a ser iniciados en la cola de entrada, el
planificador selecciona el trabajo más corto primero (SJF, Shortest Job First).
El menor tiempo restante a continuación
Una versión apropiativa del algoritmo tipo el trabajo más corto primero es el menor
tiempo restante a continuación (SRTN, Shortest Remaining Time Next). Con este
algoritmo, el planificador siempre selecciona el proceso cuyo tiempo restante de ejecución
sea el más corto. De nuevo, se debe conocer el tiempo de ejecución de antemano.
Cuando llega un nuevo trabajo, su tiempo total se compara con el tiempo restante del
proceso actual. Si el nuevo trabajo necesita menos tiempo para terminar que el proceso
actual, éste se suspende y el nuevo trabajo se inicia. Ese esquema permite que los
trabajos cortos nuevos obtengan un buen servicio.
Planificación por turno circular
Uno de los algoritmos más antiguos, simples, equitativos y de mayor uso es el de turno
circular (round-robin). A cada proceso se le asigna un intervalo de tiempo, conocido como
quántum, durante el cual se le permite ejecutarse. Si el proceso se sigue ejecutando al
final del quántum, la CPU es apropiada para dársela a otro proceso. Si el proceso se
bloquea o termina antes de que haya transcurrido el quántum, se conmuta la CPU al
siguiente proceso en la cola. Es fácil implementar el algoritmo de turno circular, todo lo
que el planificador necesita es mantener una cola de procesos listos a ejecutar, cuando el
proceso utiliza su quántum, se coloca al final de la lista.
Es importante definir la duración del quántum, si es muy corto se perderá demasiado
tiempo en conmutación de procesos o conmutación de contexto en relación al tiempo que
el proceso esté usando el CPU, por lo tanto el quántum ideal es aquel que es un promedio
de los tiempos en ejecución de los procesos a servir, si el quántum es mayor a este
promedio, este algoritmo puede comportarse como un planificador apropiativo.
Planificación por prioridad
La idea básica es simple: a cada proceso se le asigna una prioridad y el proceso
ejecutable con la prioridad más alta es el que se ejecutará a continuación.
Un posible problema de este algoritmo es que se puede generar inanición en los procesos
con prioridades bajas, una posible solución es que los procesos que están en ejecución
bajen de prioridad con cada pulso de reloj.