¿Alguna vez ha oído hablar de la Ley de Moore, que gobernó la industria de los semiconductores durante casi 60 años? ¿Sabes que la Regla de Moore nunca fue una ley, sino una observación? Para aquellos que no están familiarizados con esta ley, así es como se expresa.
La ley de Moore observa que el número de transistores en circuitos integrados densos se duplica cada dos años.
Aunque la regla está escrita en términos de electrónica, desde el punto de vista de una computadora, indica que el poder de cómputo se duplicará cada dos años. Esencialmente, la potencia computacional en un solo chip aumenta exponencialmente. ¿No es fantástico?
Lo sorprendente es que desde que se hizo esta observación, se ha demostrado que es cierta y ahora se considera una regla.
Sin embargo, como todos sabemos, las cosas bonitas no siempre son gratis. En este caso, el cálculo más poderoso se hizo a expensas de un calentamiento excesivo. Cuando llegaron en 2010, los procesadores alcanzaban temperaturas lo suficientemente altas como para cocinar pasta. (Mira este video de youtube para experimentarlo tú mismo).
Además, a medida que aumentaba el número de transistores en un chip, se empezaron a alcanzar los límites físicos del material. Las fuerzas subatómicas comenzaron a activarse en este punto, lo que dificulta mantener la trayectoria de la ley de Moore.
Parecía que los buenos tiempos habían terminado cuando las computadoras se volvían cada vez más rápidas. Pero los ingenieros tenían otros planes. Comenzaron a usar múltiples núcleos poderosos en lugar de un solo núcleo súper poderoso.
Aunque pudo haber resuelto el problema del hardware, presentó un nuevo desafío para los ingenieros de software. Los ingenieros tuvieron que desarrollar software que aprovechara los varios núcleos que ahora tenían las computadoras. Como resultado, nació la programación concurrente, a menudo conocida como programación paralela. Los subprocesos están en el centro de atención en esta área de programación. Pero antes de hablar de hilos debemos entender qué es un proceso.
Un proceso de Linux se define como una instancia en ejecución de un programa.
Por lo tanto, el sistema debe realizar un seguimiento de una serie de elementos mientras se ejecuta un programa, incluida la memoria de pila, el código fuente y los registros, entre otras cosas. En Linux, el conjunto de todas estas cosas se denomina proceso. Linux está construido sobre una base de procesos.
Para verificar los diferentes procesos que se ejecutan en su máquina, puede intentar ejecutar el siguiente comando. Esto ejecutará todos los procesos junto con su ID de proceso.
$ ps
Aquí hay una instantánea de muestra.
De forma predeterminada, el comando anterior muestra solo aquellos procesos que están asociados con el usuario actual. Para listar todos los procesos podemos usar el comando con las siguientes opciones.
$ ps -aux
Aquí hay una instantánea de muestra.
La aplicación de estas opciones adicionales al comando ps
también nos brinda información adicional. Esto es lo que significan las diferentes banderas:
a
representa a todos los usuariosu
representa al usuario actualx
muestra el proceso ejecutado fuera de la terminal
También podemos matar algunos procesos usando el comando kill
. Así es como se usa:
$ kill PID
Aquí PID
es el ID del proceso que podemos obtener del comando ps
. Cada proceso en el sistema Linux tendrá un PID
único que se usa para identificarlo. Incluso puede usar el comando pidof
para encontrar el PID
del proceso.
$ pidof bash
Cuando inicia un programa o emite un comando, se forma un proceso. Cuando ejecuta un comando desde la terminal, inicia un nuevo proceso. Debido a que se utilizó una terminal para generar este nuevo proceso, decimos que el proceso de terminal inició el nuevo proceso de comando. En otras palabras, el nuevo proceso de comando es hijo del proceso terminal.
Cada proceso en el ecosistema de Linux tiene un proceso principal que lo creó. Podemos usar el siguiente comando para verificar el proceso principal de un proceso con un PID
dado.
$ ps -o ppid= -p PID
Todos los procesos en Linux son, directa o indirectamente, hijos del proceso con PID 1. Esto no es una coincidencia. El proceso con PID 1 es el proceso de inicio y es el primer proceso iniciado por el sistema en el momento del arranque. Cualquier proceso subsiguiente se crea como un hijo de este proceso.
Así tenemos un árbol construido a partir de estas relaciones entre procesos. Esto se llama el árbol de procesos.
Los procesos son extremadamente útiles en Linux y no podríamos vivir sin ellos. Pero tienen una desventaja, o tal vez no una desventaja en absoluto, sino solo la forma en que funcionan. Un procedimiento es pesado. Los datos, la memoria y las variables se transfieren cada vez que se inicia un nuevo proceso. Cada proceso que ejecuta el mismo programa tendrá su propia copia del código fuente. Como resultado, generar una gran cantidad de procesos no es una buena idea.
Sin embargo, debido a que los procesos son un mecanismo para atender varias solicitudes al mismo tiempo, estamos limitados por esta desagradable verdad. Solo podemos atender a una pequeña cantidad de usuarios simultáneos que tienen mucho en común, ya que solo podemos iniciar una cantidad restringida de procesos en nuestro sistema. Considere un servidor web que tiene que servir a numerosos usuarios simultáneos. Crear un nuevo proceso para cada usuario es una operación costosa. Como resultado, queremos algo menos costoso que el procedimiento. Los hilos entran en juego aquí.
Los hilos son solo procesos ligeros. Un subproceso comparte memoria con su proceso principal y cualquier subproceso que haya creado. Debido a esta memoria compartida, generar nuevos subprocesos es menos costoso. Esto proporciona el beneficio adicional de una comunicación de subprocesos más rápida y un cambio de contexto. Usando subprocesos, un proceso puede realizar varias tareas al mismo tiempo.
En comparación con la cantidad de procesos, podemos generar una cantidad significativa de hilos. En máquinas con varios núcleos, estos subprocesos se ejecutan en paralelo. Cuando se opone a generar muchos procesos o realizar todas las tareas secuencialmente, esto mejora el rendimiento general del programa.
Intentemos comenzar nuestro primer hilo. Es importante tener en cuenta que no podemos iniciar nuevos hilos con bash. El comando bash solo se puede usar para crear subprocesos. Entonces, lo que haremos será escribir un código C que inicie dos subprocesos. Luego, usando bash, ejecutaremos este código C como un subproceso. Entonces, dos subprocesos serán creados por este nuevo proceso.
Empecemos a poner nuestra mano en algún código. Cree un nuevo archivo y asígnele el nombre threads.c
. Continúe y ábralo en cualquiera de sus IDE favoritos.
El primer paso es importar los archivos de encabezado necesarios.
#include <pthread.h> #include <stdio.h>
Crearemos dos hilos, cada uno ejecutando la misma función pero con diferentes parámetros. Escribamos esa función.
void* print_multiple_messages(void* ptr) { char* message = (char*) ptr; for(int i=0; i<1000; ++i) { printf("%s \n", message); } }
Como puede ver, esta función no hace nada grande. Toma un mensaje como parámetro de entrada y lo imprime mil veces.
Escribamos ahora la función principal.
int main() { // Continue writing from here }
Al igual que los procesos, los subprocesos también tienen ID que se utilizan para identificarlos de forma única. Cree dos variables para contener estos ID.
pthread_t thread1, thread2;
Usaremos diferentes mensajes para cada hilo. Cree dos cadenas (matriz de caracteres) para contener diferentes mensajes.
char* message1 = "Thread 1"; char* message2 = "Thread 2";
El siguiente paso es crear los dos hilos. Usaremos el método pthread_create
para hacerlo.
pthread_create(&thread1, NULL, print_multiple_messages, (void*) message1); pthread_create(&thread2, NULL, print_multiple_messages, (void*) message2);
Esto iniciará dos nuevos hilos. Indiquemos a nuestro proceso principal que espere hasta que los dos subprocesos hayan completado su trabajo.
pthread_join(thread1, NULL); pthread_join(thread2, NULL);
Y eso es todo. Compile el código y ejecútelo. Notará que los mensajes de dos hilos se mezclarán. Esto muestra que se están ejecutando en paralelo.
Enhorabuena, acabas de crear tu primer hilo.
Entonces, en este artículo, hablamos sobre subprocesos y procesos. Estas son algunas de las características más fascinantes de Linux, y dominarlas es crucial. Permite el desarrollo de software consciente del hardware y el uso eficiente de los recursos a nuestra disposición.
Aquí, sacaremos una conclusión de este artículo. Hicimos un esfuerzo para entrar en detalles suficientes para que pueda comenzar, pero esto no es todo. Así que sigue aprendiendo más. Si disfrutó del contenido, es posible que desee comentar y / o emocionarse.
¡Disfruta aprendiendo!