Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

Introducción a los Sistemas Operativos

¡Hola, Habr! Me gustaría llamar su atención sobre una serie de artículos, traducciones de una literatura interesante en mi opinión: OSTEP. Este material analiza con bastante profundidad el trabajo de los sistemas operativos similares a Unix, es decir, el trabajo con procesos, varios programadores, memoria y otros componentes similares que conforman un sistema operativo moderno. Puedes ver el original de todos los materiales aquí aquí. Tenga en cuenta que la traducción se hizo de manera poco profesional (con bastante libertad), pero espero haber conservado el significado general.

El trabajo de laboratorio sobre este tema se puede encontrar aquí:

Otras partes:

También puedes ver mi canal en telegrama =)

Veamos la abstracción más fundamental que el sistema operativo proporciona a los usuarios: el proceso. La definición del proceso es bastante simple: es programa en ejecución. El programa en sí es algo sin vida ubicado en el disco: es un conjunto de instrucciones y posiblemente algunos datos estáticos esperando a ser ejecutados. Es el sistema operativo el que toma esos bytes y los ejecuta, transformando el programa en algo útil.
La mayoría de las veces, los usuarios quieren ejecutar más de un programa al mismo tiempo; por ejemplo, pueden ejecutar un navegador, un juego, un reproductor multimedia, un editor de texto y similares en su computadora portátil. De hecho, un sistema típico puede ejecutar decenas o cientos de procesos simultáneamente. Este hecho hace que el sistema sea más fácil de usar, nunca tendrás que preocuparte por si la CPU está libre, simplemente ejecutas programas.

Esto plantea el problema: ¿cómo proporcionar la ilusión de muchas CPU? ¿Cómo puede el sistema operativo crear la ilusión de una cantidad casi infinita de CPU, incluso si solo tienes una CPU física?

El sistema operativo crea esta ilusión mediante la virtualización de la CPU. Al iniciar un proceso, luego detenerlo, iniciar otro proceso, etc., el sistema operativo puede mantener la ilusión de que hay muchas CPU virtuales, cuando en realidad habrá uno o más procesadores físicos. Esta técnica se llama división de recursos de CPU por tiempo. Esta técnica permite a los usuarios ejecutar tantos procesos simultáneos como deseen. El costo de esta solución es el rendimiento, ya que si varios procesos comparten la CPU, cada proceso se procesará más lentamente.
Para implementar la virtualización de la CPU, y especialmente para hacerlo bien, el sistema operativo necesita soporte tanto de bajo como de alto nivel. El soporte de bajo nivel se llama mecanismos Son métodos o protocolos de bajo nivel que implementan la parte requerida de la funcionalidad. Un ejemplo de dicha funcionalidad es el cambio de contexto, que le da al sistema operativo la capacidad de detener un programa y ejecutar otro programa en el procesador. Esta división del tiempo se implementa en todos los sistemas operativos modernos.
Además de estos mecanismos, hay cierta lógica integrada en el sistema operativo, en forma de "políticas". Política es un determinado algoritmo de toma de decisiones para el sistema operativo. Estas políticas, por ejemplo, deciden qué programa debe iniciarse (de una lista de comandos) primero. Así, por ejemplo, este problema se resolverá mediante una política llamada planificador (política de programación) y al elegir una solución, se guiará por datos como: historial de inicio (qué programa se lanzó durante más tiempo en los últimos minutos), qué carga lleva este proceso (qué tipos de programas se lanzaron), métricas de rendimiento (si el sistema está optimizado para interacción interactiva o para rendimiento) y así sucesivamente.

Abstracción: proceso

La abstracción de un programa en ejecución ejecutado por el sistema operativo es lo que llamamos proceso. Como se mencionó anteriormente, un proceso es simplemente un programa en ejecución, en cualquier período de tiempo instantáneo. Un programa con el que podemos obtener información resumida de diversos recursos del sistema a los que este programa accede o afecta durante su ejecución.
Para comprender los componentes del proceso, es necesario comprender los estados del sistema: qué puede leer o cambiar el programa durante su funcionamiento. En cualquier momento es necesario comprender qué elementos del sistema son importantes para la ejecución del programa.
Uno de los elementos obvios del estado del sistema que incluye el proceso es memoria. Las instrucciones se encuentran en la memoria. Los datos que el programa lee o escribe también se encuentran en la memoria. Así, la memoria que un proceso puede direccionar (llamada espacio de direcciones) es parte del proceso.
También forman parte del estado del sistema los registros. Muchas instrucciones tienen como objetivo cambiar el valor de los registros o leer su valor y, por lo tanto, los registros también se convierten en una parte importante del funcionamiento del proceso.
Cabe señalar que el estado de la máquina también se forma a partir de algunos registros especiales. Por ejemplo, IP - puntero de instrucción — un puntero a la instrucción que el programa se está ejecutando actualmente. También hay puntero de pila y relacionado con ello puntero de marco, que se utilizan para gestionar: parámetros de función, variables locales y direcciones de retorno.
Por último, los programas suelen acceder a la ROM (memoria de sólo lectura). Esta información de “E/S” (entrada/salida) debe incluir una lista de archivos actualmente abiertos por el proceso.

API de proceso

Para mejorar nuestra comprensión de cómo funciona el proceso, estudiemos ejemplos de llamadas al sistema que deberían incluirse en cualquier interfaz del sistema operativo. Estas API están disponibles de una forma u otra en cualquier sistema operativo.

Crear (creación): El SO debe incluir algún método que permita crear nuevos procesos. Cuando ingresa un comando en la terminal o inicia una aplicación haciendo doble clic en un ícono, se envía una llamada al sistema operativo para crear un nuevo proceso y luego iniciar el programa especificado.
Eliminación: Dado que existe una interfaz para crear un proceso, el sistema operativo también debería brindar la capacidad de forzar la eliminación de un proceso. La mayoría de los programas se iniciarán y finalizarán naturalmente por sí solos mientras se ejecutan. De lo contrario, al usuario le gustaría poder eliminarlos y, por lo tanto, sería útil una interfaz para detener el proceso.
Esperar (esperando): a veces es útil esperar a que se complete un proceso, por lo que se proporcionan algunas interfaces que brindan la posibilidad de esperar.
Control misceláneo (control variado): además de matar y esperar el proceso, también existen otros métodos de control diversos. Por ejemplo, la mayoría de los sistemas operativos brindan la capacidad de congelar un proceso (detener su ejecución durante un período determinado) y luego reanudarlo (continuar la ejecución).
Estado (estado): existen varias interfaces para obtener información sobre el estado de un proceso, como cuánto tiempo ha estado ejecutándose o en qué estado se encuentra actualmente.

Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

Creación de procesos: detalles

Una de las cosas interesantes es cómo exactamente los programas se transforman en procesos. Especialmente cómo el sistema operativo recoge y ejecuta el programa. Cómo se crea exactamente el proceso.
En primer lugar, el sistema operativo debe cargar el código del programa y los datos estáticos en la memoria (en el espacio de direcciones del proceso). Los programas suelen estar ubicados en un disco o unidad de estado sólido en algún formato ejecutable. Por lo tanto, el proceso de cargar programas y datos estáticos en la memoria requiere que el sistema operativo pueda leer esos bytes del disco y colocarlos en algún lugar de la memoria.

En los primeros sistemas operativos, el proceso de carga se realizaba con entusiasmo, lo que significa que todo el código se cargaba en la memoria antes de iniciar el programa. Los sistemas operativos modernos hacen esto de forma perezosa, es decir, cargan fragmentos de código o datos sólo cuando el programa los requiere durante su ejecución.

Una vez que el código y los datos estáticos se cargan en la memoria del sistema operativo, hay algunas cosas más que deben hacerse antes de que se pueda ejecutar el proceso. Se debe asignar cierta cantidad de memoria para la pila. Los programas utilizan la pila para variables locales, parámetros de funciones y direcciones de retorno.. El sistema operativo asigna esta memoria y se la entrega al proceso. A la pila también se le pueden asignar algunos argumentos, específicamente llena los parámetros de la función main(), por ejemplo con una matriz de argc y argv.

El sistema operativo también puede asignar algo de memoria al montón de programas. Los programas utilizan el montón para solicitar explícitamente datos asignados dinámicamente.. Los programas solicitan este espacio llamando a la función. malloc () y lo borra explícitamente llamando a la función libre(). El montón es necesario para estructuras de datos como hojas vinculadas, tablas hash, árboles y otros. Al principio, se asigna una pequeña cantidad de memoria al montón, pero con el tiempo, a medida que se ejecuta el programa, el montón puede solicitar más memoria a través de la llamada API de la biblioteca malloc(). El sistema operativo participa en el proceso de asignación de más memoria para ayudar a satisfacer estas llamadas.

El sistema operativo también realizará tareas de inicialización, particularmente aquellas relacionadas con E/S. Por ejemplo, en sistemas UNIX, cada proceso tiene de forma predeterminada 3 descriptores de archivos abiertos, para entrada, salida y error estándar. Estos identificadores permiten que los programas lean la entrada del terminal y muestren información en la pantalla.

Por lo tanto, al cargar código y datos estáticos en la memoria, crear e inicializar la pila y realizar otros trabajos relacionados con la realización de tareas de E/S, el sistema operativo prepara el escenario para que se ejecute el proceso. Finalmente, queda una última tarea: ejecutar el programa a través de su punto de entrada, llamado función main(). Al ejecutar la función main(), el sistema operativo transfiere el control de la CPU al proceso recién creado, por lo que el programa comienza a ejecutarse.

Estado del proceso

Ahora que entendemos qué es un proceso y cómo se crea, enumeremos los estados del proceso en los que puede encontrarse. En su forma más simple, un proceso puede estar en uno de estos estados:
Correr. Cuando se ejecuta, el proceso se ejecuta en el procesador. Esto significa que se están ejecutando instrucciones.
Listo!. En el estado listo, el proceso está listo para ejecutarse, pero por alguna razón el sistema operativo no lo ejecuta en el momento especificado.
Obstruido. En el estado bloqueado, un proceso realiza algunas operaciones que impiden que esté listo para ejecutarse hasta que ocurra algún evento. Un ejemplo común es cuando un proceso inicia una operación IO, se bloquea para que algún otro proceso pueda usar el procesador.

Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

Puedes imaginar estos estados en forma de gráfico. Como podemos ver en la imagen, el estado del proceso puede cambiar entre EN EJECUCIÓN y LISTO a discreción del sistema operativo. Cuando el estado de un proceso cambia de LISTO a EN EJECUCIÓN, significa que el proceso ha sido programado. En la dirección opuesta, eliminado del diseño. En el momento en que un proceso se BLOQUEA, por ejemplo, inicio una operación IO, el sistema operativo lo mantendrá en este estado hasta que ocurra algún evento, por ejemplo, la finalización de IO. en este momento se produce la transición al estado LISTO y posiblemente inmediatamente al estado EN EJECUCIÓN si el sistema operativo así lo decide.
Veamos un ejemplo de cómo dos procesos se mueven a través de estos estados. Para empezar, imaginemos que ambos procesos se están ejecutando y cada uno usa solo la CPU. En este caso, sus estados se verán así.

Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

En el siguiente ejemplo, el primer proceso, después de un tiempo de ejecución, solicita IO y entra en el estado BLOQUEADO, lo que permite ejecutar otro proceso (FIG. 1.4). El sistema operativo ve que el proceso 0 no está usando la CPU e inicia el proceso 1. Mientras se ejecuta el proceso 1, se completa IO y el estado del proceso 0 cambia a LISTO. Finalmente, el proceso 1 se ha completado y, al finalizar, el proceso 0 inicia, ejecuta y finaliza su trabajo.

Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

Estructura de datos

El sistema operativo en sí es un programa y, como cualquier otro programa, tiene algunas estructuras de datos clave que realizan un seguimiento de diversos datos relevantes. Para rastrear el estado de cada proceso, el sistema operativo admitirá algunos lista de procesos para todos los procesos en el estado LISTO y alguna información adicional para rastrear los procesos que se están ejecutando actualmente. Además, el sistema operativo debería monitorear los procesos bloqueados. Una vez completada la IO, el sistema operativo debe activar el proceso requerido y ponerlo en un estado listo para ejecutarse.

Por ejemplo, el sistema operativo debe preservar el estado de los registros del procesador. En el momento en que el proceso se detiene, el estado de los registros se almacena en el espacio de direcciones del proceso, y en el momento en que continúa su operación, se restablecen los valores de los registros y así continuar la ejecución de este proceso.

Además de los estados listo, bloqueado y en ejecución, existen otros estados. A veces, en el momento de la creación, un proceso puede estar en estado INIT. Finalmente, se puede colocar un proceso en el estado FINAL cuando ya se ha completado, pero su información aún no se ha borrado. En sistemas UNIX este estado se llama proceso zombie. Este estado es útil para los casos en los que un proceso principal desea conocer el código de retorno de un hijo; por ejemplo, normalmente 0 indica un éxito y 1 un error, pero los programadores pueden emitir códigos de salida adicionales para señalar diferentes problemas. Cuando el proceso principal finaliza, realiza una llamada final al sistema, como esperar(), para esperar a que finalice el proceso secundario e indicar al sistema operativo que puede borrar cualquier dato asociado con el proceso finalizado.

Sistemas operativos: tres piezas sencillas. Parte 2: Abstracción: Proceso (traducción)

Puntos clave de la conferencia:

proceso — la abstracción principal de un programa en ejecución en el sistema operativo. En cualquier momento dado, un proceso puede describirse por su estado: el contenido de la memoria en su espacio de direcciones, el contenido de los registros del procesador, incluidos el puntero de instrucción y el puntero de pila, e información de E/S, como los archivos abiertos que se leen o escriben.
API de proceso Consiste en llamadas que los programas pueden realizar a los procesos. Normalmente se trata de llamadas de creación, eliminación u otras llamadas.
● El proceso se encuentra en uno de muchos estados, incluido en ejecución, listo o bloqueado. Varios eventos, como la programación, las excepciones a la programación o las esperas, pueden cambiar el estado de un proceso de uno a otro.
Lista de procesos Contiene información sobre todos los procesos del sistema. Cada entrada en él se denomina bloque de control de proceso, que en realidad es una estructura que contiene toda la información necesaria sobre un proceso específico. 

Fuente: habr.com

Añadir un comentario