$30 off During Our Annual Pro Sale. View Details »

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. Redes de Computadores
    Threads
    Gustavo Pantuza
    Departamento de Ciência da Computação - UFMG
    15 de Outubro, 2014

    View Slide

  2. Introdução Processos Threads Sincronização Redes Perguntas
    Processos
    Gustavo Pantuza Threads

    View Slide

  3. 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

    View Slide

  4. 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

    View Slide

  5. 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

    View Slide

  6. Introdução Processos Threads Sincronização Redes Perguntas
    Processo com uma Thread
    Gustavo Pantuza Threads

    View Slide

  7. Introdução Processos Threads Sincronização Redes Perguntas
    Lista encadeada de processos
    Gustavo Pantuza Threads

    View Slide

  8. 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

    View Slide

  9. 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

    View Slide

  10. Introdução Processos Threads Sincronização Redes Perguntas
    Transição de estados dos processos
    Gustavo Pantuza Threads

    View Slide

  11. Introdução Processos Threads Sincronização Redes Perguntas
    Criando novos processos (clones)
    Gustavo Pantuza Threads

    View Slide

  12. Introdução Processos Threads Sincronização Redes Perguntas
    Fork
    Gustavo Pantuza Threads

    View Slide

  13. Introdução Processos Threads Sincronização Redes Perguntas
    Fork example
    1 #include
    2 #include
    3 #include /* 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

    View Slide

  14. 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

    View Slide

  15. 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

    View Slide

  16. Introdução Processos Threads Sincronização Redes Perguntas
    Threads
    Gustavo Pantuza Threads

    View Slide

  17. Introdução Processos Threads Sincronização Redes Perguntas
    Processo com multi threads
    Gustavo Pantuza Threads

    View Slide

  18. 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

    View Slide

  19. 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

    View Slide

  20. Introdução Processos Threads Sincronização Redes Perguntas
    Barreira
    Gustavo Pantuza Threads

    View Slide

  21. 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

    View Slide

  22. Introdução Processos Threads Sincronização Redes Perguntas
    Workflow com Barreira
    Gustavo Pantuza Threads

    View Slide

  23. 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

    View Slide

  24. Introdução Processos Threads Sincronização Redes Perguntas
    Mutex
    Gustavo Pantuza Threads

    View Slide

  25. 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

    View Slide

  26. 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

    View Slide

  27. 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

    View Slide

  28. Introdução Processos Threads Sincronização Redes Perguntas
    Semáforo
    Gustavo Pantuza Threads

    View Slide

  29. 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

    View Slide

  30. 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

    View Slide

  31. Introdução Processos Threads Sincronização Redes Perguntas
    Threads em requisições em rede
    Gustavo Pantuza Threads

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide