Você está na página 1de 3

Sistemas Operativos

Threads

1 Introdução
O presente guião visa pôr em prática a utilização da biblioteca Pthreads do Linux, da qual
falámos nas aulas teóricas. Vamos recordar alguns pontos essenciais sobre threads e sobre
esta biblioteca.

1.1 Noções básicas de threads


As operações básicas das thread incluem a sua criação, terminação, sincronização,
escalonamento, gestão de dados e interação de processos.

Apesar deste tipo de potencialidade, uma thread não mantém uma lista das threads criados, nem
conhece qual foi a thread que a criou. Para além disso todas as threads dentro de um processo
partilham o mesmo espaço de endereçamento.

No mesmo processo as threads partilham:

● As instruções referentes ao processo;

● A generalidades dos dados que lhe estão associados;

● Os ficheiros abertos (descritores);

● Os sinais e os seus handlers;

● A diretoria de trabalho atual;

● Identificação do utilizador e do seu grupo.

Por sua vez, cada thread possui um único:

● Identificador da thread;

● Conjunto de registos e ponteiro da pilha;

● Pilha para variáveis locais e endereços de retorno;

● Máscara do sinal;

● Prioridade associada;

● Valor de retorno: errno.

As funções pthread retornam "0" se as operações correrem de acordo com o esperado.

1.2 Criação de threads e terminação


Uma thread ou tarefa é criada recorrendo à função:
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void
*), void *arg);

onde:

● pthread_t *thread é a tarefa atual que contém o pthread id;


● pthread_attr_t *attr correspondem aos atributos a aplicar a esta tarefa; se for passado
NULL serão utilizados os parâmetros por omissão (é o que iremos fazer)
● void *(*start_routine)(void *) é a função que esta tarefa executa; e
● void *arg são os argumentos a passar para a função que a tarefa executa.

Uma tarefa termina com a terminação normal do programa que executa ou termina com a função:
void pthread_exit(void *value_ptr);

Esta função suporta a passagem de um valor de estado, que é opcional. Este valor será devolvido
às tarefas que virão a aguardar a junção com ela. Tal como no exemplo seguinte:

a função que cria a junção é:


int pthread_join(pthread_t thread, void **value_ptr);

O segundo parâmetro será a localização na memória onde é possível aceder ao estado devolvido
pela tarefa que invocou pthread_exit(). Se esse valor não for necessário, ou se a tarefa tiver
terminado duma forma normal então é possível usar NULL neste parâmetro.
De salientar que para utilizar a biblioteca Pthreads é necessário incluir pthread.h e indicar ao
linker a biblioteca pthread como se pode observar no exemplo seguinte:

$ gcc ProgramaThreads.c -o ProgramaThreads –pthread


Num projeto no Visual Studio Code, esta flag pode ser incluida na Makefile, na variável LFLAGS.

2 Exercícios Fundamentais
1. Considere o ficheiro phello.c.
a. Que alteração deve fazer para que sejam criadas 6 tarefas?
b. Faça uma chamada da função PrintHello(1000) diretamente a partir da função
main, antes de pthread_exit. Qual a tarefa que executa esta chamada à função?
c. Faça com que o parâmetro a ser passado a cada tarefa seja uma estrutura com
dois campos, 1 inteiro e um vetor de 10 carateres. O inteiro pode receber o mesmo
valor que já é passado ao programa e o vetor pode ter a mensagem “Ola!”.
d. Modifique o programa para que a mensagem “Goodbye cruel world” só seja escrita
no ecrã depois de todas as threads lançadas terminarem.

Você também pode gostar