programacion-ciclo-vida-programa

Ciclo de vida de un programa

El ciclo de vida (o ciclo de ejecución) se refiere a las diferentes etapas por las que pasa un programa desde su inicio hasta su finalización. A todo ese proceso es a lo que llamamos el ciclo de ejecución del programa.

El ciclo de vida puede ser muy sencillo, como en una aplicación de consola,

ciclo-vida-programa

En este caso, cuando lanzamos un programa este:

  • Se va a iniciar
  • Va a hacer cosas durante un rato
  • Se va a cerrar

Pero pueden llegar a ser mucho más complejos como en el caso de una aplicación de dispositivo móvil, o un juego que se ejecuta sobre un motor de videojuegos.

Por ejemplo, el ciclo de vida de una aplicación Android tiene la siguiente pinta.

ciclo-vida-android

Que como vemos, ya no es tan sencillo como inicia, ejecuta y cierra. Existen diversas formas de terminar un programa, e incluso se puede suspender y reactivar posteriormente.

El papel del sistema operativo

Durante el ciclo de vida de un programa, el sistema operativo (SO) juega un papel fundamental en cada etapa, (y cuando digo SO debemos pensar “lo que sea que estemos usando para ejecutar nuestro programa”).

En las máquinas más sencilla (como un Arduino) el “SO” es simplemente un bootloader que lanza el programa que hemos ejecutado. Otras máquinas más complejas emplean sistemas operativos ligeros como FreeRTOS.

Si hablamos de ordenador o móviles, tendremos SO como Windows, o Linux, o Android, (o el que sea). Incluso si estamos ejecutando un motor de videojuegos, este será una capa adicional de software entre nuestro programa y el hardware.

En cualquier caso, nuestro programa se va a ejecutar “a caballo” encima de varias capas de software (el tema es bastante complejo y no vamos a entrar hoy en más detalles).

Pero sí que es importante que sepáis cuando empieza la vida de ejecución de vuestro programa, cómo se ejecuta, y cuando se finaliza.

Punto de Entrada

El ciclo de vida de una aplicación comienza en el punto de entrada, que es el punto de inicio de la ejecución del programa.

En esta etapa, el SO se encarga de cargar el programa en la memoria y asignar los recursos necesarios para su ejecución. El SO también establece el entorno de ejecución y proporciona los argumentos de línea de comandos pasados al programa (como los parámetros de entrada).

En muchos lenguajes de programación, como C++ o Java, el punto de entrada suele ser una función o método con un nombre determinado, que indica por donde tiene que empezar a ejecutarse el código.

Si tomamos por ejemplo un ejemplo en C++, vemos que tiene un método main() como punto de entrada.

#include <iostream>

int main() {
    // aquí está el código que se ejecutará al principio
}

Esto sería muy similar en C# o en Java, por ejemplo. En estos lenguajes el punto de entrada al programa se indica con el método main().

Normalmente es posible cambiar el nombre del punto de entrada en la configuración del proyecto, o como opciones al compilar

En el caso de lenguajes interpretados (o semi), además del SO tenemos una capa adicional de software que es el intérprete del lenguaje. Por tanto, normalmente, en lenguajes interpretados el punto de entrada al programa sea simplemente la primera línea del mismo.

Por ejemplo, en JavaScript es suficiente con hacer,

console.log("Hola, mundo!");

No es necesario realizar más indicaciones porque el intérprete está listo para ejecutar el código tal cuál llega.

Ejecución del código

Una vez que el programa se ha cargado en la memoria y se ha establecido el entorno de ejecución, se procede a la ejecución del código en si. El programa sigue las instrucciones y realiza las operaciones definidas en el código fuente.

Durante esta etapa, el SO se encarga de gestionar el tiempo de ejecución, asignar recursos adicionales según sea necesario y garantizar un entorno de ejecución seguro y protegido.

El SO también brinda acceso a diversas funcionalidades y servicios del sistema, como la comunicación con dispositivos de entrada/salida, la gestión de archivos y la interacción con otros programas en ejecución. Además, supervisa el programa en busca de posibles errores o comportamientos anómalos que puedan afectar la estabilidad del sistema.

Finalmente, en el caso de lenguajes interpretados, además tenemos al intérprete haciendo sus labores, que también suelen incluir gestión de memoria, o entradas y salidas.

Código de salida

En algún momento el programa va a dejar de ejecutarse. Esto puede ser bien porque se apaga o reinicia la máquina donde se ejecuta, o porque el programa finaliza (vamos a obviar la parte de apagar la máquina, porque realmente no es una “finalización” controlada de un programa).

Al finalizar un programa, este informa al SO de que no tiene más tareas pendientes que realizar, y que ha terminado su función. Para ello produce un código de salida (exit code) que indica el estado en el que finalizó el programa.

El código de salida es devuelto al SO y puede ser utilizado por otros programas o scripts para tomar decisiones o realizar acciones basadas en el resultado de la ejecución.

El código de salida generalmente tiene un valor entero, donde un valor de 0 indica que el programa se ejecutó correctamente sin errores. Otros valores no nulos pueden indicar diferentes tipos de errores o condiciones excepcionales, y su interpretación puede variar según el programa y el sistema operativo.

Tras la finalización del programa, con el código de salida, el SO puede tomar las acciones oportunas (por ejemplo, liberar la memoria que había reservado para el proceso, o registrar si ha ocurrido un error durante la ejecución).

En lenguajes interpretados, generalmente no se informa al SO operativo de que el programa se ha finalizado. Porque, realmente, el SO está ejecutando el intérprete, no el programa. De forma que la gestión de finalización del proceso la realiza el propio intérprete, pero el sigue ejecutándose.