Added exercices in portuguese
This commit is contained in:
parent
7365014c96
commit
0a91d2dabd
22
10_philosophers_args.txt
Normal file
22
10_philosophers_args.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Assignment name: philosophers_args
|
||||
Expected files: philosophers_args.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create,
|
||||
pthread_detach, pthread_join, pthread_mutex_init, pthread_mutex_destroy,
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Implementa o problema completo dos filósofos com parsing de argumentos:
|
||||
|
||||
Argumentos: `number_of_philosophers time_to_die time_to_eat time_to_sleep [number_of_times_must_eat]`
|
||||
|
||||
Comportamento:
|
||||
- Cada filósofo alterna: pensar → tentar pegar forks → comer → largar forks → dormir
|
||||
- Se um filósofo não comer dentro de `time_to_die`, morre e programa termina
|
||||
- Se `number_of_times_must_eat` especificado, programa termina quando todos comeram esse número de vezes
|
||||
- Thread monitor verifica mortes a cada 1ms
|
||||
|
||||
Uso: `./philosophers_args 5 800 200 200` ou `./philosophers_args 5 800 200 200 7`
|
||||
|
||||
Hint: Este é praticamente o projeto Philosophers completo.
|
||||
Implementa parsing robusto de argumentos, validação de inputs, e cleanup adequado de recursos.
|
||||
A thread monitor é crítica - deve detectar morte rapidamente sem afetar performance.
|
||||
24
11_race_detector.txt
Normal file
24
11_race_detector.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Assignment name: race_detector
|
||||
Expected files: race_detector.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy,
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
----------------------------------------------------------------------------------------
|
||||
|
||||
Cria uma versão do problema dos filósofos que:
|
||||
1. Detecta e reporta possíveis data races
|
||||
2. Testa diferentes estratégias de otimização:
|
||||
- Estratégia A: mutex global para todas as operações
|
||||
- Estratégia B: mutex por fork + mutex para impressão
|
||||
- Estratégia C: minimizar lock time
|
||||
|
||||
Inclui stress test: roda 100 iterações com diferentes configurações e reporta:
|
||||
- Número de data races detectadas
|
||||
- Performance (tempo total)
|
||||
- Número de mortes
|
||||
|
||||
Uso: `./race_detector 4 410 200 200`
|
||||
|
||||
Hint: Use ferramentas como `valgrind --tool=helgrind` para detectar data races.
|
||||
No projeto real, qualquer data race resulta em nota 0.
|
||||
Testa com números ímpares e pares de filósofos, e com time_to_die muito próximo de time_to_eat.
|
||||
24
12_philosophers_bonus.txt
Normal file
24
12_philosophers_bonus.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Assignment name: philosophers_bonus
|
||||
Expected files: philosophers_bonus.c
|
||||
Allowed functions: memset, printf, malloc, free, write, fork, kill, exit,
|
||||
pthread_create, pthread_detach, pthread_join, usleep, gettimeofday,
|
||||
waitpid, sem_open, sem_close, sem_post, sem_wait, sem_unlink
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Implementa a versão bonus do Philosophers:
|
||||
- Cada filósofo é um processo separado (não thread)
|
||||
- Usa semáforos POSIX nomeados para coordenação
|
||||
- Processo pai monitora todos os processos filhos
|
||||
- Se um filósofo morre, mata todos os outros processos
|
||||
|
||||
Funcionalidades adicionais:
|
||||
- Cleanup adequado de semáforos nomeados
|
||||
- Handling de sinais (SIGINT, SIGTERM)
|
||||
- Relatório final com estatísticas
|
||||
|
||||
Uso: `./philosophers_bonus 5 800 200 200 7`
|
||||
|
||||
Hint: Bonus part usa processos em vez de threads.
|
||||
Semáforos POSIX nomeados permitem comunicação entre processos.
|
||||
Usa fork() para criar processos filhos e waitpid() para monitorizar.
|
||||
O cleanup de semáforos é crucial - usa sem_unlink() e handling de sinais para cleanup em caso de interrupção.
|
||||
19
1_thread_basics.txt
Normal file
19
1_thread_basics.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Assignment name: thread_basics
|
||||
Expected files: thread_basics.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create,
|
||||
pthread_detach, pthread_join, usleep, gettimeofday
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Cria um programa que lance 2 threads. Cada thread deve imprimir o seu ID e uma mensagem diferente.
|
||||
O programa principal deve esperar que ambas as threads terminem antes de sair.
|
||||
|
||||
Thread 1 deve imprimir: "Thread 1: Hello from thread 1"
|
||||
Thread 2 deve imprimir: "Thread 2: Hello from thread 2"
|
||||
|
||||
O programa deve aceitar como argumento o número de mensagens que cada thread deve imprimir.
|
||||
|
||||
Uso: `./thread_basics 5`
|
||||
|
||||
Hint: Este exercício ensina-te a base de pthread_create e pthread_join.
|
||||
Lembra-te de verificar os valores de retorno das funções pthread.
|
||||
Usa uma estrutura para passar argumentos às threads.
|
||||
18
2_mutex_basics.txt
Normal file
18
2_mutex_basics.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Assignment name: mutex_basics
|
||||
Expected files: mutex_basics.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
Cria um programa com uma variável global `counter` inicializada a 0.
|
||||
Lança 4 threads que incrementam esta variável 1000 vezes cada uma.
|
||||
Usa um mutex para proteger o acesso à variável.
|
||||
|
||||
O programa deve imprimir o valor final de `counter` (deve ser 4000) e o tempo total de execução.
|
||||
|
||||
Uso: `./mutex_basics`
|
||||
|
||||
Hint: Sem mutex, vais ver valores incorretos devido a race conditions.
|
||||
O mutex garante que apenas uma thread acede à variável de cada vez.
|
||||
Este é o conceito fundamental para o projeto Philosophers.
|
||||
23
3_precise_timing.txt
Normal file
23
3_precise_timing.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Assignment name: precise_timing
|
||||
Expected files: precise_timing.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy,
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
---------------------------------------------------------------------------------------
|
||||
|
||||
Implementa as seguintes funções:
|
||||
- `long long get_current_time()` - retorna o tempo atual em milissegundos
|
||||
- `void precise_sleep(int ms)` - dorme por exatamente X milissegundos
|
||||
- `long long time_diff(long long start, long long end)` - calcula diferença entre tempos
|
||||
|
||||
Cria um programa que testa estas funções:
|
||||
1. Mede o tempo de início
|
||||
2. Dorme por 100ms usando precise_sleep
|
||||
3. Mede o tempo de fim
|
||||
4. Imprime a diferença (deve ser ~100ms)
|
||||
|
||||
Uso: `./precise_timing`
|
||||
|
||||
Hint: gettimeofday() é crucial no projeto Philosophers.
|
||||
usleep() não é sempre preciso, por isso tens de verificar o tempo periodicamente.
|
||||
No Philosophers, o timing preciso é essencial para detectar mortes.
|
||||
23
4_state_monitor.txt
Normal file
23
4_state_monitor.txt
Normal file
@ -0,0 +1,23 @@
|
||||
**Assignment name**: state_monitor
|
||||
**Expected files**: state_monitor.c
|
||||
**Allowed functions**: memset, printf, malloc, free, write, pthread_create,
|
||||
pthread_detach, pthread_join, pthread_mutex_init, pthread_mutex_destroy,
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Cria um programa com 3 threads "worker" e 1 thread "monitor":
|
||||
|
||||
**Worker threads**: Cada thread alterna entre 3 estados:
|
||||
- WORKING (2 segundos)
|
||||
- RESTING (1 segundo)
|
||||
- THINKING (1.5 segundos)
|
||||
|
||||
Cada mudança de estado deve ser impressa com timestamp: `[timestamp] Worker X is WORKING`
|
||||
|
||||
**Monitor thread**: Verifica se algum worker está no mesmo estado há mais de 3 segundos.
|
||||
Se sim, imprime: `[timestamp] WARNING: Worker X stuck in STATE`
|
||||
|
||||
**Uso**: `./state_monitor`
|
||||
|
||||
**Hint**: Use enums para os estados. O monitor thread simula a verificação de morte no Philosophers,
|
||||
tens de verificar continuamente sem interferir com os workers. Usa mutex para proteger o acesso aos estados.
|
||||
23
5_producer_consumer.txt
Normal file
23
5_producer_consumer.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Assignment name: producer_consumer
|
||||
Expected files: producer_consumer.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create,
|
||||
pthread_detach, pthread_join, pthread_mutex_init, pthread_mutex_destroy,
|
||||
pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Implementa o problema clássico Producer-Consumer:
|
||||
- 2 threads Producer: produzem items (números de 1 a 100) e colocam num buffer
|
||||
- 2 threads Consumer: consomem items do buffer e processam-nos
|
||||
- Buffer partilhado com capacidade limitada (10 items)
|
||||
|
||||
Regras:
|
||||
- Producers devem esperar se buffer estiver cheio
|
||||
- Consumers devem esperar se buffer estiver vazio
|
||||
- Não deve haver race conditions
|
||||
- Imprime quando items são produzidos/consumidos
|
||||
|
||||
Uso: `./producer_consumer`
|
||||
|
||||
Hint: Este exercício ensina-te a coordenação entre múltiplas threads com recursos limitados.
|
||||
É similar ao problema dos forks no Philosophers.
|
||||
Usa mutexes para proteger o buffer e condition variables ou sleep para coordenação.
|
||||
24
6_deadlock_demo.txt
Normal file
24
6_deadlock_demo.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Assignment name: deadlock_demo
|
||||
Expected files: deadlock_demo.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy, pthread_mutex_lock,
|
||||
pthread_mutex_unlock, usleep, gettimeofday
|
||||
|
||||
---
|
||||
|
||||
Cria um programa que demonstra deadlock e depois mostra como o resolver:
|
||||
|
||||
Parte 1 - Deadlock:
|
||||
2 threads, 2 mutexes (mutex_a, mutex_b)
|
||||
- Thread 1: lock mutex_a → sleep 100ms → lock mutex_b → unlock ambos
|
||||
- Thread 2: lock mutex_b → sleep 100ms → lock mutex_a → unlock ambos
|
||||
|
||||
Parte 2 - Solução: Ambas threads fazem lock dos mutexes na mesma ordem.
|
||||
|
||||
O programa deve aceitar um argumento: 0 para deadlock, 1 para solução.
|
||||
|
||||
Uso: `./deadlock_demo 0` (demonstra deadlock)
|
||||
Uso: `./deadlock_demo 1` (demonstra solução)
|
||||
|
||||
Hint: Deadlock é um risco real no Philosophers quando filósofos tentam pegar forks em ordens diferentes.
|
||||
A solução mais comum é ordenar os recursos (forks com IDs mais baixos primeiro).
|
||||
23
7_limited_resources.txt
Normal file
23
7_limited_resources.txt
Normal file
@ -0,0 +1,23 @@
|
||||
**Assignment name**: limited_resources
|
||||
**Expected files**: limited_resources.c
|
||||
**Allowed functions**: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy, pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
|
||||
---
|
||||
|
||||
Simula uma biblioteca com 3 computadores partilhados entre 10 estudantes:
|
||||
- Cada estudante (thread) quer usar um computador por 2-5 segundos (tempo aleatório)
|
||||
- Apenas 3 estudantes podem usar computadores simultaneamente
|
||||
- Implementa um "semáforo" usando mutexes e uma variável contador
|
||||
|
||||
Imprime quando estudantes:
|
||||
- Chegam à biblioteca
|
||||
- Conseguem um computador
|
||||
- Terminam de usar o computador
|
||||
- Saem da biblioteca
|
||||
|
||||
**Uso**: `./limited_resources`
|
||||
|
||||
**Hint**: Como POSIX semáforos não são permitidos no mandatory part,
|
||||
implementa o teu próprio semáforo com mutex + contador + condition logic.
|
||||
Este exercício simula a limitação de recursos como no Philosophers com forks.
|
||||
19
8_simple_philosophers.txt
Normal file
19
8_simple_philosophers.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Assignment name: simple_philosophers
|
||||
Expected files: simple_philosophers.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy, pthread_mutex_lock, pthread_mutex_unlock, usleep, gettimeofday
|
||||
---
|
||||
|
||||
Implementa uma versão simplificada do problema dos filósofos:
|
||||
- 3 filósofos sentados numa mesa circular
|
||||
- 3 forks (um entre cada par de filósofos)
|
||||
- Cada filósofo alterna entre: pensar (1s) → pegar forks → comer (1s) → largar forks → repetir
|
||||
- Programa corre por 10 segundos e depois pára
|
||||
|
||||
Cada ação deve ser impressa: `[timestamp] Philosopher X is thinking/eating`
|
||||
|
||||
Uso: `./simple_philosophers`
|
||||
|
||||
Hint: Este é o núcleo do projeto Philosophers. Cada fork é protegido por um mutex.
|
||||
Para evitar deadlock, implementa uma ordem consistente para pegar forks (fork com ID menor primeiro).
|
||||
Usa uma thread monitor para parar após 10s.
|
||||
21
9_death_monitor.txt
Normal file
21
9_death_monitor.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Assignment name: death_monitor
|
||||
Expected files: death_monitor.c
|
||||
Allowed functions: memset, printf, malloc, free, write, pthread_create, pthread_detach,
|
||||
pthread_join, pthread_mutex_init, pthread_mutex_destroy, pthread_mutex_lock,
|
||||
pthread_mutex_unlock, usleep, gettimeofday
|
||||
---
|
||||
|
||||
Cria um sistema com:
|
||||
- 4 threads "worker" que fazem trabalho por períodos variados (1-4 segundos)
|
||||
- 1 thread monitor que verifica se algum worker não dá "sinal de vida" há mais de 3 segundos
|
||||
- Workers devem atualizar `last_activity_time` a cada iteração
|
||||
- Monitor verifica a cada 100ms e imprime aviso se detectar worker "morto"
|
||||
|
||||
Simula "morte" fazendo um worker parar aleatoriamente.
|
||||
|
||||
Uso: `./death_monitor`
|
||||
|
||||
Hint: Este exercício simula a detecção de morte no Philosophers.
|
||||
O monitor thread deve verificar continuamente sem bloquear os workers.
|
||||
Usa mutex para proteger `last_activity_time`.
|
||||
A detecção deve ser rápida (dentro de 10ms no projeto real).
|
||||
2
LICENSE
2
LICENSE
@ -219,7 +219,7 @@ If you develop a new program, and you want it to be of the greatest possible use
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
philosophers_training
|
||||
philosophers_prep
|
||||
Copyright (C) 2025 ruiferna
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
62
README.md
62
README.md
@ -1,2 +1,62 @@
|
||||
# philosophers_training
|
||||
# Exercícios Preparatórios — Projeto Philosophers
|
||||
|
||||
Bem-vindo ao repositório de exercícios práticos desenhados para construir, passo a passo, todos os conceitos necessários para dominar o projeto Philosophers da 42. Aqui vais encontrar desafios progressivos sobre threads, mutexes, deadlocks, sincronização, semáforos, timing, e muito mais em C.
|
||||
|
||||
## Objetivo
|
||||
|
||||
A proposta deste repositório é guiar estudantes pela aprendizagem real de programação concorrente, partindo do absoluto básico até à implementação de sistemas completos e robustos capazes de resolver o clássico problema dos Filósofos, incluindo as regras e desafios da bonus part.
|
||||
|
||||
## Estrutura dos Exercícios
|
||||
|
||||
Cada exercício segue uma estrutura clara e normalizada, incluindo:
|
||||
|
||||
- **Assignment name**
|
||||
- **Expected files**
|
||||
- **Allowed functions**
|
||||
- **Descrição do problema**
|
||||
- **Sugestão/Hint para a resolução**
|
||||
|
||||
### Lista de Exercícios
|
||||
|
||||
| Nº | Nome | Conteúdo-chave |
|
||||
|----|---------------------------|---------------------------------------------|
|
||||
| 1 | thread_basics | Threads, pthread_create, pthread_join |
|
||||
| 2 | mutex_basics | Mutexes, race conditions |
|
||||
| 3 | precise_timing | gettimeofday, usleep, timing |
|
||||
| 4 | state_monitor | Monitorização, enums, padrões monitor |
|
||||
| 5 | producer_consumer | Sincronização, coordination problems |
|
||||
| 6 | deadlock_demo | Deadlock, prevenção de deadlock |
|
||||
| 7 | limited_resources | Semáforo manual, acesso limitado |
|
||||
| 8 | simple_philosophers | Problema dos filósofos simplificado |
|
||||
| 9 | death_monitor | Monitorização de vida, threads watchdog |
|
||||
| 10 | philosophers_args | Implementação 'full', argumentos |
|
||||
| 11 | race_detector | Data races, otimização de locks |
|
||||
| 12 | philosophers_bonus | Processos, semáforos POSIX, bonus part |
|
||||
|
||||
## Como usar
|
||||
|
||||
1. **Cada exercício é independente.** Recomenda-se seguir pela ordem, para garantir a aprendizagem progressiva.
|
||||
2. **Compilar cada exercício:**
|
||||
```sh
|
||||
gcc -Wall -Wextra -Werror -pthread <nome_ficheiro>.c -o <programa>
|
||||
```
|
||||
3. **Executar cada binário** seguindo as instruções e exemplos do cabeçalho do exercício.
|
||||
|
||||
## Requisitos Técnicos
|
||||
|
||||
- Compilador C (ex: gcc)
|
||||
- Ambiente POSIX (Linux ou Mac OS X recomendado)
|
||||
- Bibliotecas pthreads standard
|
||||
|
||||
## Recomendações
|
||||
|
||||
- Não uses funções externas às permitidas.
|
||||
- Lê atentamente os hints fornecidos para cada exercício.
|
||||
- Analisa erros de race condition e deadlocks usando ferramentas como `valgrind --tool=helgrind`.
|
||||
- Consulta [The Little Book of Semaphores](https://greenteapress.com/wp/semaphores/) para cimentar conceitos.
|
||||
|
||||
## Créditos e Referências
|
||||
|
||||
- Inspirado no livro open-source **The Little Book of Semaphores** por Allen B. Downey.
|
||||
- Estrutura e avaliação baseadas no formato dos projetos 42.
|
||||
- Problema clássico dos Filósofos por Edsger W. Dijkstra.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user