Se os threads compartilham o mesmo PID, como eles podem ser identificados?

Eu tenho uma consulta relacionada à implementação de threads no Linux.

O Linux não possui suporte explícito a threads. No userspace, podemos usar uma biblioteca de threads (como o NPTL) para criar threads. Agora, se usarmos o NPTL, ele suportará o mapeamento 1: 1.

O kernel usará a function clone() para implementar threads.

Suponha que eu tenha criado 4 threads. Então isso significaria que:

  • Haverá 4 task_struct .
  • Dentro da task_struct , haverá provisão de resources de compartilhamento de acordo com os argumentos para clonar (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) .

Agora tenho a seguinte consulta:

  1. Os 4 tópicos terão o mesmo PID? Se alguém puder elaborar, como os PIDs são compartilhados.
  2. Como os diferentes encadeamentos são identificados? Existe algum conceito TID (Thread ID)?

    Os quatro threads terão o mesmo PID, mas somente quando vistos de cima. O que você (como usuário) chama de PID não é o que o kernel (olhando de baixo) chama de PID.

    No kernel, cada thread tem seu próprio ID, chamado PID (embora possa fazer mais sentido chamar isto de TID, ou ID de thread) e eles também têm um TGID (ID do grupo de threads) que é o PID do encadeamento. que iniciou todo o processo.

    Simplisticamente, quando um novo processo é criado, ele aparece como um encadeamento onde tanto o PID quanto o TGID são o mesmo (novo) número.

    Quando um encadeamento inicia outro encadeamento, esse encadeamento iniciado obtém seu próprio PID (para que o planejador possa agendá-lo independentemente), mas ele herda o TGID do encadeamento original.

    Dessa forma, o kernel pode agendar facilmente os threads, independentemente do processo a que pertencem, enquanto os processos (IDs do grupo de threads) são reportados a você.

    A seguinte hierarquia de threads pode ajudar (a) :

      USER VIEW < -- PID 43 --> < ----------------- PID 42 -----------------> +---------+ | process | _| pid=42 |_ _/ | tgid=42 | \_ (new thread) _ _ (fork) _/ +---------+ \ / +---------+ +---------+ | process | | process | | pid=44 | | pid=43 | | tgid=42 | | tgid=43 | +---------+ +---------+ < -- PID 43 --> < --------- PID 42 --------> < --- PID 44 ---> KERNEL VIEW 

    Você pode ver que iniciar um novo processo (à esquerda) fornece um novo PID e um novo TGID (ambos configurados com o mesmo valor), enquanto o início de um novo thread (à direita) fornece um novo PID, mantendo o mesmo TGID como o segmento que o iniciou.


    (a) Tremer de admiração pelas minhas impressionantes habilidades gráficas 🙂

    Threads são identificados usando PIDs e TGID (ID do grupo de threads). Eles também sabem qual encadeamento é pai de quem, essencialmente, um processo compartilha seu PID com qualquer encadeamento iniciado. As identificações de thread geralmente são gerenciadas pela própria biblioteca de threads (como pthread, etc …). Se os 4 threads forem iniciados, eles devem ter o mesmo PID. O kernel em si irá lidar com o agendamento de threads e tal, mas a biblioteca é a que vai gerenciar os threads (se eles podem ser executados ou não, dependendo do seu uso de junit de thread e methods de espera).

    Nota: Isto é da minha lembrança do kernel 2.6.36. Meu trabalho nas versões atuais do kernel está na camada de E / S, então não sei se isso mudou desde então.

    O Linux fornece a chamada do sistema fork() com a funcionalidade tradicional de duplicar um processo. O Linux também fornece a capacidade de criar encadeamentos usando a chamada do sistema clone() No entanto, o linux não distingue entre processos e encadeamentos.