Google

terça-feira, 15 de abril de 2008

Threads e Processos

Como vários "programas" podem rodar simultaneamente em um PC se ele possui um único processador?

Multiprogramação: o processador é chaveado entre diversos programas dando a cada um algumas dezenas de milissegundos de processamento produzindo a ilusão de paralelismo (pseudo-paralelismo).

Criação de processos

MS-DOS: suspende a execução do processo pai até que o filho termine sua execução.

UNIX: operação fork (cria cópia extra do processo pai) (pai e filho rodando em pseudo-paralelismo). No processo filho, fork retorna 0 (zero). No processo pai, fork retorna o identificador do processo filho.

Threads ou processos leves

fork() : uma cópia idêntica do processo pai é criada => cópia do código, das variáveis, recursos do SO (arquivos abertos, sinais, etc.) => dispendioso.

Threads (processos leves): fluxo de execução dentro do mesmo processo compartilhando dados e recursos do processo. Em UNIX (Linux), um thread:
* Existe dentro de um processo e usa os recursos do processo;
* Tem o seu próprio fluxo de controle independente enquanto existir o processo pai e o SO dá suporte a ele;
* Pode compartilhar os recursos do processo com outros threads igualmente independentes;
* Morre se o seu processo pai morre
Para um programador, o conceito de um "procedimento" ou "função" que roda independentemente do seu programa principal pode ser a melhor descrição de uma thread.

Um processo é criado pelo sistema operacional e contém informações sobre os recursos de um programa e seu estado de execução, incluindo:

* id do processo, do grupo de processos, do usuário e do grupo do usuário;
* ambiente;
* diretório de trabalho;
* instruções do programa;
* registradores;
* pilha do programa;
* heap (memória alocada dinamicamente);
* descritores de arquivos;
* ações para sinais recebidos;
* bibliotecas compartilhadas;
* ferramentas para comunicação entre processos (mensagens, pipes, memória compartilhada).

Threads usam e existem dentro destes recursos, mas são capazes de ser escalonados pelo sistema operacional e de rodar como entidades independentes dentro de um processo. Um thread pode ter um fluxo independente de controle e ser escalonado porque mantém:

* o seu próprio PC (contador de programa);
* o seu próprio ponteiro de pilha (stack pointer);
* os seus próprios registradores;
* as suas próprias propriedades de escalonamento (e.g. prioridades, etc.);
* o seu próprio conjunto de sinais pendentes e bloqueados;
* e seus próprios dados que lhe são específicos.

Um processo pode conter muitos threads, e todos eles compartilham os recursos dentro do processo e são executados dentro do mesmo espaço de endereçamento. Dentro de um programa com múltiplos threads há simultaneamente múltiplos pontos de execução.

Devido ao fato de threads dentro do mesmo processo compartilharem recursos:

* mudanças feitas por um thread a um recurso compartilhado do sistema (como alterar variável global ou fechar um arquivo) serão vistas por todos os outros threads;
* dois ponteiros que têm o mesmo valor, apontam para o mesmo dado;
* leitura e escrita das mesmas posições de memória são possíveis, e, portanto, há a necessidade de sincronização explícita pelo programador.

Fonte: ANDREW S. TANENBAUM - Sistemas Operacionais Modernos

Mas como implementar isso? Há alguns anos atrás achava que era impossível, mas agora vejo que não tem segredo algum nisso:
Exemplo de processos (fork - Unix):
void main(void)
{
pid_t pid;
pid = fork();
if (pid
<0)
perror("ERRO DE FORK\n");
else
if (pid>0)
{
do
{
<comandos do processo pai>
}while(aux==0);
}
else
{
<comandos do processo filho>
}
exit(0);
}

Versão para download
O processo pai cria outro processo (filho) idêntico e ficará aguardando até o filho terminar, ou seja retornar 0 (zero) para finalizar a execução dos processos. Na versão para download está implementado como tratar o retorno que é fornecido pelo processo filho.
Exemplo de threads:

int main(void)
{
pthread_t thread1;
pthread_t thread2;
char *message1 = "Hello World";
char *message2 = "Hello Brazil";
pthread_create(&thread1,NULL,(void*)&print_message_function,(void*)message1);
pthread_join(thread1,NULL);

pthread_create(&thread2,NULL,(void*)&print_message_function2,(void*)message2);
pthread_join(thread2,NULL);

exit(0);
}

void print_message_function(void *ptr)
{
char *message;
message=(char *) ptr;
printf("%s \n\n",message);
}
void print_message_function2(void *ptr)
{
char *message;
message=(char *) ptr;
printf("%s \n\n",message);
}


Versão para download

Nenhum comentário:

Postagens populares