Sunteți pe pagina 1din 6

1. Programao em Pthreads 1.1.

Introduo A biblioteca de pthreads cumpre os padres POSIX e nos permite trabalhar com diferentes "traos de execuo" (threads) ao mesmo tempo. A diferena entre uma thread e um processo que os processos no compartilham memria entre si a no ser que seja declarado explicitamente usando algum dos mecanismos de IPC (InterProcess Communication) de Unix, j as threads compartilham totalmente a memria entre elas. Alm do mais, para criar threads sao usadas as funes da biblioteca "pthread" ou de qualquer outra que suporte "threads" e para criar processos usaremos a chamada de sistema fork(), que encontrada em todos os sistemas unix. Como pthreads uma biblioteca POSIX possvel portar os programas feitos com ela para qualquer sistema operacional POSIX que suporte threads. Exemplos disso so IRIX, BSD, Digital Unix OSF/1, etc. 1.2. Como compilar um programa com pthreads: Para criar programas que faam uso de biblioteca pthread precisamos, em primeiro lugar, da biblioteca em si. Esta vem na maioria de distribuies do linux, e seguramente instalada juntamente com os outros pacotes para o desenvolvimento de aplicaes. Uma vez que tenhamos a biblioteca instalada, deveremos compilar o programa e "linkalo" biblioteca dependendo do compilador que estamos usando. A forma mais usual de fazer isto , se estamos usando um compilador GNU gcc, com o seguinte comando: cc programa_com_pthreads.c -o programa_com_pthreads -pthread 1.3. Criao e manipulao de threads Para criar uma thread usaremos a funo pthread_create da biblioteca e da estrutura de dados pthread_t que identifica cada thread diferenciando-a das demais e que contem todos os seus dados. O prottipo da funo o seguinte: int pthread_create(pthread_t * thread, pthread_attr_t *attr, void * (*start_routine)(void *), void *arg) * thread: uma varivel do tipo pthread_t que conter os dados da thread e que nos servir para identificar a thread quando nos interessar fazer chamadas a biblioteca para realizar alguma ao sobre ela. * attr: um parmetro do tipo pthread_attr_t que se deve inicializar previamente com os atributos que queremos que a thread tenha. Entre os atributos esto a prioridade, o algoritmo da thread, etc. Se passarmos como parmetro NULL, a biblioteca atribuir a thread atributos por default.

* start_routine: aqui colocamos o endereo da funo que queremos que a thread execute. A funo deve devolver um ponteiro genrico (void *) como resultado, e deve ter como nico parmetro um outro ponteiro genrico. A vantagem dos ponteiros serem genricos que podemos devolver qualquer coisa que se queira atravs dos castings dos tipos. Se necessitarmos passar ou devolver mais de um parmetro de uma vez, se pode criar uma estrutura e incluir ali tudo o que necessrio. Logo passaremos ou devolveremos o caminho desta estrutura como um nico parmetro. (ver cdigo do exemplo) * arg: um ponteiro ao parmetro que passaremos para a funo. Pode ser NULL se no quisermos passar nada para a funo. * Em caso de sucesso, a funo retorna 0 ou um valor de diferente de 0 caso tenha havido algum erro.

Uma vez que tenhamos chamado esta funo, j teremos a(s) nossa(s) thread(s) funcionando, mas agora temos duas opes: esperar que as threads terminem, caso nos interesse recuperar algum resultado, ou simplesmente deixamos a biblioteca de pthreads decidir que quando termine a execuo da funo da thread elimine todas os dados de suas tabelas internas. Para isso, dispomos de duas funes adicionais da biblioteca: pthread_join e pthread_detach. int pthread_join(pthread_t th, void **thread_return) * Esta funo suspende a thread que a chamou at que termine a execuo da thread indicada por th. Alm do mais, uma vez que esta ltima termina, o resultado colocado em thread_return devolvendo para a thread que estava executando. * th: o identificador da thread que queremos esperar, e o mesmo que indicamos quando criamos com o pthread_create. * thread_return: um ponteiro de um ponteiro que aponta para o resultado devolvido pela thread que estamos esperando quando esta termina a sua execuo. Se este parmetro for NULL, estamos dizendo que o resultado no importa. * Devolve 0 em caso de sucesso, e valor diferente de 0 em caso de algum erro. int pthread_detach(pthread_t th) * Esta funo indica para a biblioteca que no queremos que o resultado da thread indicada por th seja guardado. Por padro, o resultado da execuo de todas as threads so guardados at que faamos um pthread_join para recuperar o resultado. por isso que se no nos interessa o resultado das threads temos que indicar isso com esta funo. Assim uma vez que a thread tenha terminado, a biblioteca eliminar todos os dados da thread de suas tabelas internas e teremos mais espao para criar outras threads.

* th: o indentificador da thread. * Devolve 0 em caso de sucesso, e valor diferente de 0 em caso de algum erro. At agora estivemos falando sobre devolver valores quando a thread finaliza, mas no dizemos como se faz. Pois bem, para isso temos a funo pthread_exit. void pthread_exit(void *retval) * Esta funo termina a execuo da thread que a chama. * retval: um ponteiro genrico para os dados que queremos retornar como resultado. Estes dados sero recolhidos mais tarde quando algum fizer um pthread_join com o nosso identificador de thread. * No devolve nenhum valor. Com tudo que vimos at agora, j estamos preparados para fazer nosso primeiro problema com pthreads. O programa de exemplo criar MAX_THREADS threads que executaro a funo function_thr. Esta funo imprimir uma mensagem na tela do tipo "sou a thread nmero x", onde x ser um nmero diferente para cada thread. Para passar estes parmetros para a funo usaremos um struct de C, onde colocaremos o vetor que dever conter cada thread juntamente com seu identificador. (Esta cadeia poderia ser colocada diretamente dentro da funo, mas desta forma aproveitaremos para ver como fazer para passar mais de um parmetro para a thread) Uma vez que termine sua execuo, a thread devolver com resultado seu identificador (codificado em um inteiro), que ser impresso na tela pela "thread-pai" que esperar que todas as outras threads terminem. exemplo: /*** Arquivo ex1.c ***/ #include #include #include #include #define MAX_THREADS 10 //tabela com os identificadores das threads pthread_t tabela_thr[MAX_THREADS]; //tipo de dados e tabela com os parmetros typedef struc { int id; char *cadeia; } thr_param_t; thr_param_t param[MAX_THREADS]; //Tivemos que criar uma tabela para os parmetros pois os passamos por referncia.

//Assim, se s tivermos uma varivel para os parmetros, ao modific-la estaremos //modificando todas as que havamos passado anteriomente, porque as threads no //armazenam os valores e sim os endereos void *funo_thr(thr_param_t *p) { //Esta a funo que as threads executam //Como se pode ver no h maiores segredos printf("%s %d\n", p->cadeia, p->id); //Uma vez que terminamos, devolvemos o valor pthread_exit(&(p->id)); } int main (void) { int i, *res; //criamos as theads printf("Criando as threads...\n"); for(i=0; i param[i].cadeia = strdup("Ol, sou a thread"); param[i].id = i; pthread_create(&tabela_thr[i], NULL, (void*)&funo_thr, (void*) & param[i]); } //esperamos que as threads terminem printf("Threads criadas. Esperando que terminem...\n"); for(i=0; i pthread_join(tabela_thr[i], (void*)&res); printf("A thread %d retornou o valor %d\n", i, *res); } //imprimimos uma mensagem e saimos do programa printf("Todas as threads terminadas!\n"); return(0); } fim do exemplo! Para compilar (com o gcc do Linux): gcc ex1.c -o ex1 -pthread O exemplo em si bastante simples, mas o esquema bsico ao qual seguem todas as aplicaes que criam uma thread para realizar um clculo e esperam por seu resultado de retorno:

1. Criar a(s) thread(s) 2. Esperar que termine(m) 3. Recolher e processar os resultados Isto um exemplo do que chamamos de paralelismo estruturado. Um exemplo de um programa que use a funo pthread_detach poderia ser o de um servidor (de qualquer coisa: de correio, de http, de ftp, etc) que crie um trao de execuo para cada solicitao que receba. Como o que nos interessa o resultado da execuo, uma vez que crirmos uma thread chamaremos a funo pthread_detach. Isto o que se conhece por paralelismo no estruturado. Ou seja, nossos programas no seguem uma estrutura concreta, e vo se ramificando de acordo com as nossas necessidades.

1.4. Outras funes teis da biblioteca pthread: At agora vimos apenas as funes mais bsicas para se tratar com pthreads. Comearemos ento a analisar outras funes teis: 1) pthread_t pthread_self(void) - Esta funo retorna para a thread que realiza a chamada sua informao, em forma de varivel do tipo pthread_t. til nos casos em que a prpria thread que se est executando quer trocar seus atributos, ou seja, fazer em si mesma um pthread_detach, etc. - Devolve o identificador da thread. Exemplo: #include ... void *funcion_threads(void *param) { pthread_t eu_mesmo; ... /*ns mesmo nos fazemos o detach*/ eu_mesmo = pthread_self(); pthread_detacc(eu_mesmo); ... } int main (void) { ... }

2) int pthread_kill(pthread_t thread, int signo) - Envia um sinal especfico para a a thread especificada. Um sinal til pode ser o SIGKILL, ou algum dos definidos pelo usurio, SIGUSR1 e SIGUSR2. Mesmo que possa parecer til primeira vista, a nica utilidade que tem matar uma thread a partir do processo pai. Se quiseres usar um com fins de sincronizao, h formas melhores de se fazer, tratando-se de threads: mediante semforos e variveis de condio (veremos em seguida). - thread: identifica a thread para a qual queremos enviar o sinal. - signo: nmero do sinal que queremos enviar para a thread. Podemos usar as constantes definidas em usr/include/signa.h. - Retorna 0 se no ocorrer erro, e diferente de 0 se houver erro.

S-ar putea să vă placă și