Slide 1

Slide 1 text

Redes de Computadores Threads Gustavo Pantuza Departamento de Ciência da Computação - UFMG 15 de Outubro, 2014

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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