Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Threads em C

Threads em C

Aula sobre Threads em C

Gustavo Pantuza

October 15, 2014
Tweet

More Decks by Gustavo Pantuza

Other Decks in Programming

Transcript

  1. Introdução Processos Threads Sincronização Redes Perguntas Processos Um Processo é

    basicamente um programa em execução Um programa é apenas o código. Um programa pode executar vários processos Associado a cada processo está seu espaço de endereçamento Gustavo Pantuza Threads
  2. Introdução Processos Threads Sincronização Redes Perguntas Espaço de endereçamento Contém

    o programa executável e os recursos do programa. Recursos como: registradores (contador de progra e ponteiro para a pilha); lista de arquivos abertos; alarmes abertos (eventos e signals do SO); processos relacionados; Gustavo Pantuza Threads
  3. Introdução Processos Threads Sincronização Redes Perguntas Threads É a menor

    unidade de processamento de um processo, um fluxo de controle. Cada processo tem um espaço de endereçamento e, no mínimo, uma thread. Um processo tem duas partes: Ativa: fluxo de controle e execução (Thread) Passiva: espaço de endereçamento Threads de um mesmo processo compartilham do mesmo espaço de endereçamento. Gustavo Pantuza Threads
  4. Introdução Processos Threads Sincronização Redes Perguntas Processos versus Threads O

    Linux escalona Tarefas (tasks) As tarefas são threads ou processos single-threaded Um processo é um conjunto de threads compartilhando o mesmo espaço de endereçamento O escalonador de tarefas do Linux não diferencia threads de processos Gustavo Pantuza Threads
  5. Introdução Processos Threads Sincronização Redes Perguntas Task structure 1 struct

    task_struct { 2 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ 3 long counter, priority; 4 unsigned long signal; 5 unsigned long blocked; /* bitmap of masked signals */ 6 unsigned long flags; /* per process flags, defined below */ 7 struct task_struct *next_task, *prev_task, *next_run, *prev_run; 8 unsigned long saved_kernel_stack; 9 int pid, pgrp; 10 struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; 11 unsigned long timeout, policy, rt_priority; 12 long utime, stime, cutime, cstime, start_time; 13 struct files_struct *files; /* open file information */ 14 struct mm_struct *mm; /* memory management info */ 15 struct signal_struct *sig; /* signal handlers */ 16 }; Figura: task_struct usada na lista de processos Gustavo Pantuza Threads
  6. Introdução Processos Threads Sincronização Redes Perguntas Fork example 1 #include

    <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> /* fork */ 4 #define CHILD 0 5 int main(int argc, char* argv[]) 6 { 7 int num = 0; 8 /*Fork return the Child process id (PID) to Parent process. 9 * The child process pid variable must be 0 */ 10 int pid = fork(); 11 fprintf(stdout,"Both process run this line where number is: %d\n", num); 12 if(pid == CHILD){ /* Child Process */ 13 num = 1; 14 fprintf(stdout, "I am the CHILD and the number now is %d\n", num); 15 }else if(pid > 0){ /* Parent Process */ 16 num = 2; 17 fprintf(stdout, "I am the PARENT and the number now is %d\n", num); 18 } 19 printf("Who am I? the number for me is %d\n", num); return EXIT_SUCCESS; 20 } Figura: Very simple fork() example Gustavo Pantuza Threads
  7. Introdução Processos Threads Sincronização Redes Perguntas Fork utilizando wait() 1

    int main() { 2 pid_t childpid; /* variable to store the child’s pid */ 3 int retval; /* child process: user-provided return code */ 4 int status; /* parent process: child’s exit status */ 5 childpid = fork(); 6 if (childpid >= 0) { /* fork succeeded */ 7 if (childpid == 0) { /* fork() returns 0 to the child process */ 8 printf("CHILD: Here’s my PID: %d\n", getpid()); 9 sleep(1); printf("CHILD: Enter an exit value (0 to 255): "); 10 scanf(" %d", &retval); printf("CHILD: Goodbye!\n"); 11 exit(retval); /* child exits with user-provided return code */ 12 } else { /* fork() returns new pid to the parent process */ 13 printf("PARENT: Here’s my PID: %d\n", getpid()); wait(&status); 14 printf("PARENT: Child’s exit code: %d\n", WEXITSTATUS(status)); 15 printf("PARENT: Goodbye!\n"); exit(EXIT_SUCCESS); 16 } 17 } else { /* fork returns -1 on failure */ 18 perror("fork"); exit(EXIT_FAILURE); 19 } 20 } Figura: fork() example with wait() Gustavo Pantuza Threads
  8. Introdução Processos Threads Sincronização Redes Perguntas System call System call

    para criação de processos (fork()) 1 clone(SIGCHLD, 0); System call para criação de threads (pthread) 1 clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0); Gustavo Pantuza Threads
  9. Introdução Processos Threads Sincronização Redes Perguntas Criando Threads Utiliza a

    lib pthread.h A função pthread_create() cria uma thread dentro do processo. A função passada como parâmetro é o bloco a ser executado pela thread A função pthread_join() aguarda até que a thread finalize sua execução Gustavo Pantuza Threads
  10. Introdução Processos Threads Sincronização Redes Perguntas Criando threads com pthread

    1 typedef struct str_thdata { 2 int thread_no; 3 char message[100]; 4 } thdata; 5 int main() { 6 pthread_t thread1, thread2; /* thread variables */ 7 thdata data1, data2; /* structs to be passed to threads */ 8 /* initialize data to pass to thread 1 and 2 */ 9 data1.thread_no = 1; 10 strcpy(data1.message, "Hello!"); 11 data2.thread_no = 2; 12 strcpy(data2.message, "Hi!"); 13 /* create threads 1 and 2 */ 14 pthread_create (&thread1, NULL, (void *) &print_msg, (void *) &data1); 15 pthread_create (&thread2, NULL, (void *) &print_msg, (void *) &data2); 16 /* Waits for threads to finish */ 17 pthread_join(thread1, NULL); 18 pthread_join(thread2, NULL); 19 exit(0); 20 } Figura: exemplo com pthread Gustavo Pantuza Threads
  11. Introdução Processos Threads Sincronização Redes Perguntas Barreira Barreira é um

    ponto de parada na execução do programa Qualquer process/thread é obrigado a parar na barreira Nenhum dos processos ou threads pode continuar até que todos os outros também tenham alcançados a barreira Gustavo Pantuza Threads
  12. Introdução Processos Threads Sincronização Redes Perguntas Utilizando barreiras com pthread

    1 #define N_THREADS 10 2 pthread_barrier_t barrier; 3 void* print_num (void *data) { 4 fprintf(stdout, "thread %u: reached the barrier\n", (unsigned long) ← pthread_self()); 5 pthread_barrier_wait(&barrier); sleep(1); 6 fprintf(stdout, "thread %u: Now running ...\n", (unsigned long) ← pthread_self()); 7 } 8 int main (int argc, char *argv[]) { 9 pthread_barrier_init(&barrier, NULL, N_THREADS); 10 pthread_t threads[N_THREADS]; int i = 0; 11 for (;i < N_THREADS; i++) { 12 pthread_create(&threads[i], NULL, &print_num, NULL); 13 } 14 for (i=0; i < N_THREADS; i++) { 15 pthread_join(threads[i], NULL); 16 } 17 return EXIT_SUCCESS; 18 } Figura: Exemplo de Barreira Gustavo Pantuza Threads
  13. Introdução Processos Threads Sincronização Redes Perguntas Condição de corrida O

    resultado da computação em dois processos que compartilham um mesmo recurso depende de quem executa primeiro Ex: Duas threads tentanto alterar a mesma variável. As partes de um programa que acessam esses recursos compartilhados são chamadas de regiões críticas. Gustavo Pantuza Threads
  14. Introdução Processos Threads Sincronização Redes Perguntas Exclusão Mútua Para permitir

    que programas executem de maneira segura suas regiões críticas é necessário utilizar o princípio de Exclusão Mútua. Ela é uma forma de impedir que outros processos/threads façam uso de algum recurso compartilhado quando um processo o estiver usando. Ex: Só uma thread usa a variável por vez O mutex é uma implementação da Exclusão Mútua Gustavo Pantuza Threads
  15. Introdução Processos Threads Sincronização Redes Perguntas Exemplo utilizando Mutex 1

    pthread_mutex_t mutex; 2 void* modify_num (void *data) { 3 sleep(3); int *num = (int *) data; 4 pthread_mutex_lock(&mutex); /* Critical region */ *num = 0; 5 fprintf(stdout, "thread %d: Entering critical region\n",pthread_self()); 6 fprintf(stdout, "I’m a bad thread. Nobody move! num is now %d\n", *num); 7 sleep(3); pthread_mutex_unlock(&mutex); 8 fprintf(stdout, "thread %d: Exiting critical region\n", pthread_self()); 9 } 10 int main (int argc, char *argv[]) { 11 pthread_mutex_init(&mutex, NULL); pthread_t thread; int num = 0; 12 pthread_create(&thread, NULL, &modify_num, (void *) &num); 13 for (int i = 0; i < N_ITERATIONS; i++) { 14 pthread_mutex_lock(&mutex); 15 fprintf(stdout, "num is %d\n", num++); 16 pthread_mutex_unlock(&mutex); sleep(1); 17 } 18 pthread_join(thread, NULL); pthread_mutex_destroy(&mutex); 19 return EXIT_SUCCESS; 20 } Figura: Exemplo de Mutex Gustavo Pantuza Threads
  16. Introdução Processos Threads Sincronização Redes Perguntas Semáforo Implementa a Exclusão

    Mútua Um Mutex gera Espera Ocupada A Espera Ocupada é quando um processo verifica uma condição repetidamente até que ela seja verdadeira Ela ocupa o processador junto com os demais processos. Ineficiente Semáforos colocam o processo pra dormir (wait state) O processo é acordado quando o semáforo é incrementado Gustavo Pantuza Threads
  17. Introdução Processos Threads Sincronização Redes Perguntas Exemplo utilizando Semáforo 1

    #define THREADS 20 2 #define N_MILKS 4 3 sem_t OKToBuyMilk; int milkAvailable; 4 void* buyer(void *arg) { 5 sem_wait(&OKToBuyMilk); 6 if(milkAvailable < N_MILKS) 7 ++milkAvailable; 8 sem_post(&OKToBuyMilk); return NULL; 9 } 10 int main(int argc, char **argv) { 11 pthread_t threads[THREADS]; milkAvailable = 0; 12 sem_init(&OKToBuyMilk, 0, 1); 13 for(int i = 0; i < THREADS; ++i) 14 pthread_create(&threads[i], NULL, &buyer, NULL); 15 for(int i = 0; i < THREADS; ++i) 16 pthread_join(threads[i], NULL); 17 sem_destroy(&OKToBuyMilk); 18 printf("Total milk: %d\n", milkAvailable); 19 return EXIT_SUCCESS; 20 } Figura: Exemplo de Semáforo Gustavo Pantuza Threads
  18. Introdução Processos Threads Sincronização Redes Perguntas Threads em requisições em

    rede Imagine uma arquitetura cliente/servidor utilizando sockets O servidor pode criar threads para lidar com as requisições recebidas Gustavo Pantuza Threads
  19. Introdução Processos Threads Sincronização Redes Perguntas Threads em requisições em

    rede 1 void handler(void * paramsd) { 2 ... 3 while(readnf(client_local, line)!=ERROR) 4 { 5 /* Process the request send() recv() */ 6 } 7 } 8 9 int main (int argc, char* argv[]) { 10 ... 11 while(1) { 12 addr_len = sizeof(cliAddr); 13 client = accept(server, (struct sockaddr *) &cliAddr, (socklen_t *)&← addr_len); 14 pthread_create(&thread, 0, (void*)&handler, (void*) &client); 15 } 16 } Figura: Exemplo utilizando threads para manipular requisições Gustavo Pantuza Threads
  20. Introdução Processos Threads Sincronização Redes Perguntas Dúvidas? Contatos: email: [email protected]

    github: pantuza twitter: @gpantuza site: http://pantuza.com Gustavo Pantuza Threads