GNU/Linux >> Tutoriales Linux >  >> Linux

¿Se implementan los subprocesos como procesos en Linux?

Creo que esto es parte del clone(2) La página de manual puede aclarar la diferencia re. el ID:

CLONE_THREAD (desde Linux 2.4.0-test8)
Si se establece CLONE_THREAD, el hijo se coloca en el mismo grupo de subprocesos que el proceso de llamada.
Los grupos de subprocesos fueron una característica agregada en Linux 2.4 para admitir la noción de subprocesos POSIX de un conjunto de subprocesos que comparten un solo PID. Internamente, este PID compartido es el llamado identificador de grupo de subprocesos (TGID) para el grupo de subprocesos. Desde Linux2.4, las llamadas a getpid(2) devuelven el TGID de la persona que llama.

La frase "los subprocesos se implementan como procesos" se refiere al problema de los subprocesos que tenían PID separados en el pasado. Básicamente, Linux originalmente no tenía subprocesos dentro de un proceso, solo procesos separados (con PID separados) que podrían haber tenido algunos recursos compartidos, como memoria virtual o descriptores de archivos. CLONE_THREAD y la separación de la ID del proceso y la ID del subproceso hacen que el comportamiento de Linux se parezca más a otros sistemas y más a los requisitos de POSIX en este sentido. Aunque técnicamente, el sistema operativo aún no tiene implementaciones separadas para subprocesos y procesos.

El manejo de señales fue otra área problemática con la implementación anterior, esto se describe con más detalle en el documento al que @FooF se refiere en su respuesta.

Como se señaló en los comentarios, Linux 2.4 también se lanzó en 2001, el mismo año que el libro, por lo que no sorprende que la noticia no haya llegado a esa impresión.


Tienes razón, de hecho "algo debe haber cambiado entre 2001 y ahora". El libro que está leyendo describe el mundo de acuerdo con la primera implementación histórica de subprocesos POSIX en Linux, llamada LinuxThreads (consulte también el artículo de Wikipedia para ver algunos).

LinuxThreads tuvo algunos problemas de compatibilidad con el estándar POSIX, por ejemplo, hilos que no comparten PID, y algunos otros problemas graves. Para corregir estas fallas, Red Hat encabezó otra implementación llamada NPTL (Biblioteca de subprocesos POSIX nativos) para agregar el kernel necesario y el soporte de biblioteca de espacio de usuario para lograr un mejor cumplimiento de POSIX (tomando buenas partes de otro proyecto de reimplementación de la competencia de IBM llamado NGPT (" Próxima generación de subprocesos Posix"), consulte el artículo de Wikipedia sobre NPTL). Las banderas adicionales agregadas al clone(2) llamada al sistema (en particular, CLONE_THREAD que @ikkkachu señala en su respuesta) es probablemente la parte más evidente de las modificaciones del núcleo. La parte del espacio de usuario del trabajo finalmente se incorporó a la biblioteca GNU C.

Todavía hoy en día, algunos SDK de Linux integrados usan la antigua implementación de LinuxThreads porque están usando una versión de LibC con menor consumo de memoria llamada uClibc (también llamada µClibc), y pasó una gran cantidad de años antes de que se transfiriera la implementación del espacio de usuario NPTL de GNU LibC y se asume como la implementación de subprocesos POSIX predeterminada, ya que, en términos generales, estas plataformas especiales no se esfuerzan por seguir las últimas modas a la velocidad del rayo. El uso de la implementación de LinuxThreads en funcionamiento se puede observar al notar que, de hecho, los PID para diferentes subprocesos en esas plataformas son diferentes a diferencia de lo que especifica el estándar POSIX, tal como lo describe el libro que está leyendo. De hecho, una vez que llamaste a pthread_create() , de repente aumentó el recuento de procesos de uno a tres, ya que se necesitaba un proceso adicional para mantener el desorden unido.

La página del manual de Linux pthreads(7) proporciona una descripción completa e interesante de las diferencias entre los dos. Otra descripción esclarecedora, aunque desactualizada, de las diferencias es este artículo de Ulrich Depper e Ingo Molnar sobre el diseño de NPTL.

Te recomiendo que no te tomes esa parte del libro demasiado en serio. En cambio, recomiendo los subprocesos POSIX de programación de Butenhof y las páginas del manual POSIX y Linux sobre el tema. Muchos tutoriales sobre el tema son inexactos.


Los subprocesos (espacio de usuario) no se implementan como procesos como tales en Linux, ya que no tienen su propio espacio de direcciones privado, aún comparten el espacio de direcciones del proceso principal.

Sin embargo, estos subprocesos se implementan para usar el sistema de contabilidad de procesos del núcleo, por lo que se les asigna su propia ID de subproceso (TID), pero reciben el mismo PID e 'ID de grupo de subprocesos' (TGID) que el proceso principal; esto contrasta con una bifurcación, donde se crean un nuevo TGID y PID, y el TID es el mismo que el PID.

Así que parece que los núcleos recientes tenían un TID separado que se puede consultar, es esto lo que es diferente para los subprocesos, un fragmento de código adecuado para mostrar esto en cada uno de los main() thread_function() arriba es:

    long tid = syscall(SYS_gettid);
    printf("%ld\n", tid);

Así que el código completo con esto sería:

#include <pthread.h>                                                                                                                                          
#include <stdio.h>                                                                                                                                            
#include <unistd.h>                                                                                                                                           
#include <syscall.h>                                                                                                                                          

void* thread_function (void* arg)                                                                                                                             
{                                                                                                                                                             
    long tid = syscall(SYS_gettid);                                                                                                                           
    printf("child thread TID is %ld\n", tid);                                                                                                                 
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());                                                                                            
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return NULL;                                                                                                                                              
}                                                                                                                                                             

int main ()                                                                                                                                                   
{                                                                                                                                               
    pthread_t thread;                                                                               
    long tid = syscall(SYS_gettid);     
    printf("main TID is %ld\n", tid);                                                                                             
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());                                                    
    pthread_create (&thread, NULL, &thread_function, NULL);                                           
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return 0;                                                                                                                                                 
} 

Dando un ejemplo de salida de:

main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963

Linux
  1. Cómo matar procesos en ejecución en Linux

  2. comando linux ps

  3. Descubra los procesos huérfanos de Linux

  4. Introducción a los subprocesos de Linux - Parte I

  5. ¿Qué son los procesos, subprocesos, procesos ligeros y estado del proceso de Linux?

Comando Ps en Linux (Lista de Procesos)

Comando Pgrep en Linux

Comando Linux PS con ejemplos

Averigüe qué procesos están escuchando en un puerto particular en Linux

Supervisión de procesos en Linux

Comprender los procesos en Linux