Processos: Execute um programa que contenha um segmento de execução
Relatório de pesquisa: Processos: Execute um programa que contenha um segmento de execução. Pesquise 861.000+ trabalhos acadêmicosPor: fichmam • 8/12/2014 • Relatório de pesquisa • 1.288 Palavras (6 Páginas) • 356 Visualizações
THREADS
Idéia básica
Processos: programa em execução que contém um único fluxo de execução.
Threads: programa em execução com múltiplos fluxos de execução. Em sistemas tradicionais, cada processo tem seu espaço de endereçamento individual e apenas um fluxo de execução (thread). No entanto, algumas vezes desejamos ter vários fluxos de execução no mesmo espaço de endereçamento e uma execução paralela.
Visão Geral
Thread ou linha de execução é uma das maneiras utilizadas por um processo para dividir a si mesmo em duas ou mais tarefas que podem ser executadas simultaneamente, em geral, em arquiteturas multiprocessadas. O suporte à thread é fornecido pelo próprio sistema operacional (SO), no caso da Kernel-Level Thread (KLT), ou implementada através de uma biblioteca de uma determinada linguagem, no caso de uma User-Level Thread (ULT).
Um exemplo pode ser dado através de um jogo onde o mesmo pode ser modelado com linhas de execução diferentes, sendo uma para desenho de imagem e outra para áudio. Nesta aplicação, teríamos uma thread para tratar rotinas de desenho e outra thread para tratar instruções do áudio. Para o usuário, a imagem é desenhada ao mesmo tempo em que o áudio é emitido pelos auto-falantes. No entanto, para sistemas com uma única CPU, cada linha de execução é processada por vez [1].
Assim, as threads permitem um paralelismo de granularidade mais fina (paralelismo de instruções). Por granularidade mais fina, subentende-se que a unidade de cálculo realizada de maneira concorrente é menor do que a unidade de cálculo associada a um processo (paralelismo de aplicações, por exemplo). A granularidade de uma thread pode ser, por exemplo, um método ou um conjunto de instruções dentro de um programa. Para isso ser possível, cada thread mantém um contador de programa (PC – Program Counter) e um registrador de instruções (IR- Instruction Register) para dizer qual instrução é a próxima a ser executada e qual está sendo processada, respectivamente. Além de registradores que contém suas variáveis atuais de trabalho, pilha com o histórico das instruções executadas e o estado de cada variável. Para que uma thread possa ser executada ela deve pertencer a algum processo, ou seja, um processo deve ser criado anteriormente. Dessa forma, podemos dizer que processos são usados para agrupar recursos (espaço de endereçamento com o código do programa, variáveis globais, etc) enquanto as threads são as entidades escalonadas pela CPU para a execução de tarefas.
Threads são conhecidas como processos leves. Basicamente, esse atributo se deve ao menor tempo gasto em atividades de criação e escalonamento de threads, se comparadas aos processos. O compartilhamento de memória entre as threads maximiza o uso dos espaços de endereçamento e torna mais eficiente o uso destes dispositivos. Como todas as threads tem exatamente o mesmo espaço de endereçamento, eles também compartilham as mesmas variáveis globais. Assim, como cada thread pode acessar qualquer posição de memória dentro do espaço de endereçamento do processo, é possível a um thread ler, escrever ou até apagar informações usadas por outra thread. Não existe um meio de proteção para isso, fica sob responsabilidade do usuário este cuidado já que normalmente criamos threads para cooperar e não competir. O escalonamento entre threads acontece da mesma forma que entre processos. Portanto, cada thread tem o mesmo contexto de software e compartilha o mesmo espaço de memória de um mesmo processo pai. Contudo, o contexto de hardware de cada fluxo de execução é diferente. Conseqüentemente, o tempo “perdido” com o escalonamento das threads é muito menor do que o escalonamento de processos. Além disso, não há acesso protegido a memória nativamente (a implementação é de responsabilidade do programador) devido ao compartilhamento do espaço de memória [1].
Uma das vantagens do uso de threads está no fato do processo poder ser dividido em mais de uma linha de execução. Quando uma thread está esperando determinado dispositivo de I/O ou qualquer outro recurso do sistema, o processo como um todo não precisa ser bloqueado, pois quando uma thread entra no estado de bloqueio uma outra thread do mesmo processo está aguardando na fila de prontos para dar continuidade a execução do programa [1].
Normalmente, criamos um processo com um único thread e a partir deste cria-se novas threads através de comandos do tipo thread_create( ). Geralmente passamos como parâmetro um nome de um procedimento para informar o que a thread deve executar. Como resultado do comando temos um identificador/nome para a thread criada. Ao finalizar seu trabalho a thread pode chamar uma função do tipo thread_exit e desaparecer para não ser mais escalonável. Assim como os processos, as threads possuem estados durante o ciclo de vida. Os estados atingidos são os mesmos discutidos em processos. Uma tabela de threads deve então ser mantida para armazenar informações individuais de cada fluxo de execução. Essa tabela é denominada TCB e contém:
1. o endereço da pilha;
2. o contador de programa;
3. registrador de instruções
4. registradores de dados, endereços, flags;
5. endereços das threads filhas;
6. estado de execução.
Resta para o processo,
...