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

98

Tenho uma dúvida relacionada à implementação de threads no Linux.

O Linux não tem suporte a thread explícito. No espaço do usuário, podemos usar uma biblioteca de threads (como NPTL) para criar threads. Agora, se usarmos NPTL, ele suporta mapeamento 1: 1.

O kernel usará a clone()função para implementar threads.

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

  • Haverá 4 task_struct.
  • Dentro do task_struct, haverá provisão de compartilhamento de recursos de acordo com os argumentos a serem clonados (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Agora tenho a seguinte consulta:

  1. Os 4 threads terão o mesmo PID? Se alguém puder explicar, como os PIDs são compartilhados.
  2. Como são identificados os diferentes segmentos; existe algum conceito de TID (thread ID)?
SPSN
fonte

Respostas:

274

Os quatro threads terão o mesmo PID, mas apenas 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 de PID (embora possivelmente faça mais sentido chamá-lo de TID ou ID de thread) e eles também têm um TGID (ID de grupo de thread) que é o PID do thread que iniciou todo o processo.

De forma simplista, quando um novo processo é criado, ele aparece como uma thread em que o PID e 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 herda o TGID do encadeamento original.

Dessa forma, o kernel pode agendar threads alegremente independentemente de qual processo eles pertencem, enquanto os processos (IDs de grupo de threads) são relatados 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 definidos com o mesmo valor), enquanto iniciar um novo thread (à direita) fornece um novo PID, mantendo o mesmo TGID como o tópico que o iniciou.


(a) Tremer de admiração com minhas impressionantes habilidades gráficas :-)

paxdiablo
fonte
20
FYI, getpid()retorna tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}conforme mostrado em www.makelinux.com/
Duke
6
@Duke - uau, é por isso que não consegui encontrar uma gettgid(2)função. E o getpid()não vai retornar o TID ("PID" do thread), e é aí que gettid(2)entra. Dessa forma eu posso dizer se estamos no thread principal ou não.
Tomasz Gandor
2
Isso leva a outro ponto interessante: Então, se threads e processos são tratados igualmente dentro do kernel (além do tgid), um processo multi-threaded irá, em conclusão, obter mais tempo de CPU do que um single-threaded, desde que ambos tenham o mesmo prioridade e nenhum dos encadeamentos é interrompido por qualquer motivo (como esperar por um mutex).
Aconcágua
1
@Aconcagua, CFS (o agendador completamente justo no Linux) geralmente funciona dessa forma, mas também permite o uso de extensões do agendador de grupo para fazer a justiça operar em certos grupos de tarefas em vez de tarefas individuais. Eu nunca realmente olhei para ele além de um olhar superficial.
paxdiablo
'' getpgrp '' para obter o id do grupo
Pengcheng
2

Os threads são identificados usando PIDs e TGID (ID do grupo de threads). Eles também sabem qual thread é pai de quem, portanto, essencialmente, um processo compartilha seu PID com qualquer thread que iniciar. IDs de thread são geralmente gerenciados pela própria biblioteca de thread (como pthread, etc ...). Se os 4 threads forem iniciados, eles devem ter o mesmo PID. O próprio kernel irá lidar com o agendamento de threads e tal, mas a biblioteca é quem irá gerenciar as threads (se eles podem ser executados ou não, dependendo do uso dos métodos de junção de thread e espera).

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

Jesus Ramos
fonte
-6

O Linux fornece à fork()chamada de sistema a funcionalidade tradicional de duplicação de um processo. O Linux também oferece a capacidade de criar threads usando a clone()chamada de sistema. No entanto, o linux não faz distinção entre processos e thread.

SAUNDARYA KUMAR GUPTA
fonte