Quais tópicos compartilham em geral?

20

Bem, esta é uma pergunta geral. E se alguém quiser torná-lo específico da implementação, preferirei coisas relacionadas ao Unix. Mas primeiro é necessário conhecer os seguintes problemas em geral:

Eu li processo único pode ter vários segmentos. Vários threads do mesmo processo compartilham coisas entre eles. Eu quero saber o que eles compartilham e o que não. Considerando que o processo é composto por espaço de endereço, pilha, pilha, variáveis ​​globais, código, dados, recursos do SO, o que entre eles é compartilhado por threads? Eu tenho os seguintes palpites:

  1. Variáveis ​​globais - eu li variável global de compartilhamentos de threads. Também durante a programação em Java e C #, criei threads para compartilhar variáveis ​​no nível de classe. Portanto, acredito que os threads compartilham variáveis ​​globais (embora não tenham certeza se os conceitos em linguagens de programação de alto nível se traduzem em fatos de baixo nível de sistema operacional).

  2. Heap - Como a variável global é armazenada no heap, o heap é compartilhado entre os threads.

  3. Pilha - Como cada thread pode ter sua própria sequência / código de execução, ela deve ter sua própria pilha na qual pode enviar / exibir seu conteúdo do contador de programas (quando, por exemplo, ocorrem chamadas e retornos de função). Portanto, os threads do mesmo processo não compartilham a pilha.

Agora não tenho certeza sobre o compartilhamento das seguintes coisas

  1. Espaço de endereço - Não sei ao certo o que conta exatamente no espaço de endereço. Mas acho que o espaço de endereço geralmente é usado no contexto de processos, não em threads. E como todos os threads do mesmo processo residem no mesmo espaço de endereço do processo pai, diz-se que os threads compartilham o espaço de endereço. (Mas eles mantêm pilhas diferentes dentro do mesmo espaço de endereço?)

  2. Recursos do SO - Eu acho que isso pode ser muito específico da implementação. Por exemplo, o processo pai pode seletivamente fornecer identificador do mesmo arquivo para alguns de seus threads e não para todos. Ou eu estou enganando e recursos do SO significa algo diferente de arquivos?

  3. Código - Os encadeamentos podem ter código diferente, portanto, nem sempre é o caso de compartilhar código.

  4. Dados - inseguro sobre o que considerar nos dados. Mas verifique se as variáveis ​​globais são compartilhadas entre os threads. E certifique-se de que as variáveis ​​locais não sejam compartilhadas da mesma forma.

No geral, estou consideravelmente confuso devido a termos vagos, super-generalizações feitas nos livros de Sistemas Operacionais e detalhes específicos de extra-implementação fornecidos on-line. Então, eu estou tentando encontrar alguma resposta que possa me satisfazer.

Maha
fonte

Respostas:

13

Em geral, cada encadeamento possui seus próprios registradores (incluindo seu próprio contador de programa), seu próprio ponteiro de pilha e sua própria pilha. Todo o resto é compartilhado entre os threads que compartilham um processo.

Em particular , geralmente considera-se que um processo consiste em um conjunto de encadeamentos que compartilham um espaço de endereço, heap, dados estáticos e segmentos de código e descritores de arquivo * .

Um espaço de endereço é simplesmente o mapeamento de endereços lógicos para partes específicas da memória física. Portanto, quando dizemos que todos os threads em um processo compartilham o mesmo espaço de endereço, queremos dizer que, ao acessar uma variável foono escopo global, todos os threads verão a mesma variável. Da mesma forma, os segmentos podem estar executando um ponto diferente no código a qualquer momento específico, mas todos têm permissão para chamar a função global bar(), que corresponderá à mesma função para todos os segmentos no processo.

A maioria dos sistemas operacionais modernos adicionou uma noção de armazenamento local de encadeamento , que são variáveis ​​do escopo global que não são compartilhadas. O exemplo usual da utilização das isto é para a variável errno. Essa é uma variável única do escopo global, mas na maioria dos sistemas operacionais modernos, cada segmento recebe sua própria cópia local, para que um erro em uma chamada de biblioteca em um segmento não afete o comportamento de outros segmentos.

* Há algum estado de processo adicional compartilhado por todos os threads em um processo, como a identificação do processo, a manipulação de sinal e os bloqueios de arquivo. Para obter uma lista completa do estado do processo compartilhado pelos encadeamentos, é necessário consultar a documentação para a implementação de encadeamento específica. Por exemplo, a página de manual pthreads .

Lógica Errante
fonte
4

Os threads aparecem em duas perspectivas: sistemas operacionais e linguagens de programação. Nos dois casos, há alguma variação nos atributos de um encadeamento.

Uma definição mínima de um thread é que são coisas que acontecem em sequência, uma coisa após a outra.

Em um modelo de execução de máquina típico, cada encadeamento possui seu próprio conjunto de registradores de uso geral e seu próprio contador de programa. Se a máquina definir um registro específico como ponteiro de pilha, haverá uma cópia por encadeamento.

Da perspectiva do sistema operacional, o mínimo que um sistema operacional precisa fazer para oferecer suporte a threads é fornecer uma maneira de alternar entre eles. Isso pode acontecer automaticamente ( multitarefa premptiva ou apenas quando o encadeamento faz uma solicitação explícita (multitarefa cooperativa; nesse caso, os encadeamentos às vezes são chamados de fibras ). Existem também modelos híbridos com rendimentos de preferência e de cooperação, por exemplo, preempção entre encadeamentos de diferentes grupos ou tarefas, mas rendimentos explícitos entre threads do mesmo grupo / tarefa.A alternância entre threads envolve no mínimo salvar os valores de registro do thread antigo e restaurar os valores de registro do novo thread.

Em um sistema operacional multitarefa que fornece isolamento entre tarefas (ou processos , você pode tratar esses termos como sinônimos em um contexto do SO), cada tarefa possui seus próprios recursos, em particular o espaço de endereço, mas também abre arquivos, privilégios, etc. a ser fornecido pelo kernel do sistema operacional , uma entidade que está acima dos processos. Cada tarefa normalmente possui pelo menos um thread - uma tarefa que não executa código não é muito útil. O sistema operacional pode ou não suportar vários encadeamentos na mesma tarefa; por exemplo, o Unix original não. Uma tarefa ainda pode executar vários threads organizando a alternância entre eles - isso não requer privilégios especiais. Isso é chamado de " threads de usuário "”, Especialmente em um contexto Unix. Atualmente, a maioria dos sistemas Unix fornece threads do kernel, principalmente porque é a única maneira de ter vários threads do mesmo processo em execução em diferentes processadores.

A maioria dos recursos do sistema operacional, além do tempo de computação, é anexada a tarefas, não a threads. Alguns sistemas operacionais (por exemplo, Linux) delimitam explicitamente as pilhas; nesse caso, cada encadeamento possui o seu; mas existem sistemas operacionais nos quais o kernel não sabe nada sobre pilhas, eles são apenas parte do heap no que diz respeito. O kernel também geralmente gerencia um contexto de kernel para cada thread, que é uma estrutura de dados que contém informações sobre o que o thread está fazendo atualmente; isso permite que o kernel lide com vários threads bloqueados em uma chamada do sistema ao mesmo tempo.

No que diz respeito ao sistema operacional, os threads de uma tarefa executam o mesmo código, mas estão em posições diferentes nesse código (valores diferentes do contador de programa). Pode ou não acontecer que certas partes do código de um programa sejam sempre executadas em um thread específico, mas geralmente existe um código comum (por exemplo, funções utilitárias) que pode ser chamado de qualquer thread. Todos os threads veem os mesmos dados, caso contrário, seriam considerados tarefas diferentes; se alguns dados puderem ser acessados ​​apenas por um encadeamento específico, isso geralmente é da competência da linguagem de programação, não do sistema operacional.

Na maioria das linguagens de programação, o armazenamento é compartilhado entre os threads do mesmo programa. Este é um modelo de memória compartilhada de programação simultânea; é muito popular, mas também propenso a erros, porque o programador precisa ter cuidado quando os mesmos dados puderem ser acessados ​​por vários threads como podem ocorrer condições de corrida . Observe que mesmo variáveis ​​locais podem ser compartilhadas entre threads: “variável local” (geralmente) significa uma variável cujo nome é válido apenas durante uma execução de uma função, mas outra thread pode obter um ponteiro para essa variável e acessá-la.

Também existem linguagens de programação em que cada thread tem seu próprio armazenamento, e a comunicação entre elas ocorre enviando mensagens pelos canais de comunicação. Isto é o modelo de transmissão de mensagens da programação simultânea. Erlangé a principal linguagem de programação que se concentra na passagem de mensagens; seu ambiente de execução possui um manuseio muito leve de threads e incentiva programas escritos com muitos threads de curta duração, em contraste com a maioria das outras linguagens de programação em que a criação de um thread é uma operação relativamente cara e o ambiente de tempo de execução não pode suportar um tamanho muito grande. número de threads ao mesmo tempo. O subconjunto seqüencial de Erlang (a parte da linguagem que ocorre em um thread, em particular a manipulação de dados) é (principalmente) puramente funcional; portanto, um thread pode enviar uma mensagem para outro thread que contém alguns dados e nenhum deles precisa se preocupar com os dados que estão sendo modificados pelo outro enquanto o estiver usando.

Alguns idiomas combinam os dois modelos, oferecendo armazenamento local de encadeamento, com ou sem um sistema de tipos para distinguir o local de armazenamento local de encadeamento dos globais. O armazenamento local de encadeamentos geralmente é um recurso de conveniência que permite que um nome de variável designe diferentes locais de armazenamento em encadeamentos diferentes.

Alguns acompanhamentos (difíceis) que podem ser interessantes para entender o que são tópicos:

  • Qual é o mínimo que um kernel precisa fazer para suportar vários threads?
  • Em um ambiente multiprocessador, o que é necessário para migrar um encadeamento de um processador para outro?
  • O que seria necessário para implementar multithreading cooperativo ( corotinas ) em sua linguagem de programação favorita, sem suporte do sistema operacional e sem usar o suporte interno, se houver? (Lembre-se de que a maioria das linguagens de programação não possui as primitivas necessárias para implementar corotinas em um único encadeamento.)
  • Como seria uma linguagem de programação se tivesse simultaneidade, mas nenhum conceito (explícito) de threads? (Exemplo principal: o cálculo pi ).
Gilles 'SO- parar de ser mau'
fonte
Esta é a coisa mais interessante que li em meses.
JSON
2

Depende. Se você considerar os tópicos definidos, por exemplo, pelo POSIX (e oferecido pelos sistemas Unix) ou pelo Windows (não familiarizado com o posterior, você teria que perguntar especificamente), isso dará sua resposta (essencialmente como a resposta da @WanderingLogic explica). O Linux tem sua própria idéia de encadeamentos, usando a clone(2)chamada de sistema não padrão . Oferece controle bastante refinado do que os pais e os filhos compartilham. Ele chega a ter fork(2)e vfork(2)envolve essencialmente o interno clone(2), chamando-o com sinalizadores específicos, ou seja, você pode criar "threads" que compartilham quase nada com o pai. Consulte sua página de manual para obter detalhes, eles estão disponíveis on-line, por exemplo, aqui . Sim, o Linux oferece threads no estilo POSIX, mas muito mais.

vonbrand
fonte
0

Compartilhamento de tópicos:

  • Espaço de endereço
  • Montão
  • Dados estáticos
  • Segmentos de código
  • Descritores de arquivo
  • Variáveis ​​globais
  • Processos filho
  • Alarmes pendentes
  • Sinais e manipuladores de sinais
  • Informação contábil

Os threads têm seus próprios:

  • Contador de programa
  • Registros
  • Pilha
  • Estado
ericcurtina
fonte