Skip to content

Commit e98b0ae

Browse files
committed
aula14
1 parent 184ae5f commit e98b0ae

8 files changed

Lines changed: 410 additions & 157 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <unistd.h>
2+
#include <stdio.h>
3+
4+
int main(int argc, char *argv[]) {
5+
for (int i = 0; i < argc; i++) {
6+
printf("arg: %s\n", argv[i]);
7+
}
8+
9+
return 0;
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <unistd.h>
2+
#include <stdio.h>
3+
4+
int main(int argc, char *argv[]) {
5+
char prog[] = "ls";
6+
// a lista de argumentos sempre começa com o nome do
7+
// programa e termina com NULL
8+
char *args[] = {"ls", "-l", "-a", NULL};
9+
10+
execvp(prog, args);
11+
12+
printf("Fim do exec!\n");
13+
14+
return 0;
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <sys/types.h>
2+
#include <sys/wait.h>
3+
#include <unistd.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
7+
int main() {
8+
pid_t filho;
9+
10+
filho = fork();
11+
12+
if (filho == 0) {
13+
sleep(3);
14+
printf("Acabei filho %d\n", 1);
15+
16+
return 2;
17+
} else {
18+
int wstatus;
19+
wait(&wstatus);
20+
printf("Filho acabou\n");
21+
printf("Terminou normal?: %d\n", WIFEXITED(wstatus));
22+
printf("Valor de retorno: %d\n", WEXITSTATUS(wstatus));
23+
24+
}
25+
return 0;
26+
}

content/aulas/14-exec/index.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# 14 - Carregamento de programas
2+
3+
!!! pdf
4+
![](slides.pdf)
5+
6+
<br>
7+
8+
9+
## Argumentos de um programa
10+
11+
Leia com atenção o código antes de responder os próximos exercícios.
12+
13+
```cpp
14+
int main(int argc, char *argv[]) {
15+
for (int i = 0; i < argc; i++) {
16+
printf("arg: %s\n", argv[i]);
17+
}
18+
19+
return 0;
20+
}
21+
```
22+
23+
Suponha que o código `exemplo-args.c` acima foi compilado para o programa `exemplo-args`. Considerando a invocação a seguir `exemplo-args teste var bla foo`, responda às perguntas abaixo **sem rodar o programa**.
24+
25+
!!! exercise text choice
26+
Qual os valores de `argc` e `argv`?
27+
28+
- [ ] `argc=1, argv={"exemplo-args"}`
29+
- [x] `argc=5, argv={"exemplo-args", "teste", "var", "bla", "foo"}`
30+
- [ ] `argc=4, argv={"teste", "var", "bla", "foo"}`
31+
- [ ] `argc=3, argv={"teste", "var", "bla", "foo"}`
32+
33+
!!! answer "Resposta"
34+
São 5 argumentos, contando com `argv[0]` sendo o nome do programa chamado.
35+
36+
!!! exercise text short
37+
Qual seria a saída do programa para a invocação acima?
38+
39+
!!! answer "Resposta"
40+
```
41+
exemplo-args
42+
teste
43+
var
44+
bla
45+
foo
46+
```
47+
48+
!!! exercise text short
49+
Qual o significado de `argv[0]`?
50+
51+
!!! answer "Resposta"
52+
É o nome do programa chamado.
53+
54+
!!! example
55+
Crie um programa `soma` que tem o seguinte comportamento:
56+
57+
1. Se o programa for chamado com menos de 2 argumentos mostrar mensagem de erro e sair.
58+
1. Se o programa for chamado com 2 ou mais argumentos, mostrar no terminal a soma deles.
59+
1. Se um argumento não for um número considerá-lo como 0.
60+
61+
**Dica**: execute `man atof` no terminal ;)
62+
63+
## Carregando novos programas com `exec`
64+
65+
A chamada `exec` é usada para carregar programas na memória e executá-los. O novo programa é carregado no contexto do processo atual, substituindo-o por completo. Veja um exemplo de uso correto do `execvp` abaixo, o código fonte está em `exemplo-exec.c`.
66+
67+
```cpp
68+
char prog[] = "ls";
69+
// a lista de argumentos sempre começa com o nome do
70+
// programa e termina com NULL
71+
char *args[] = {"ls", "-l", "-a", NULL};
72+
73+
execvp(prog, args);
74+
printf("Fim do exec!\n");
75+
```
76+
77+
!!! exercise text choice
78+
Supondo que o `execvp` funcione, a linha `printf("Fim do exec!\n")` executa?
79+
80+
- [ ] SIM
81+
- [x] NÃO
82+
83+
!!! answer "Resposta"
84+
A linha não é executada se o `execvp` funcionar. O programa antigo é completamente substituído pelo novo programa quando o `execvp` funciona.
85+
86+
Os argumentos passados no `execvp` são passados para o `main` do programa executado via argumentos do `main`. Ao fazer a chamada
87+
88+
```cpp
89+
char prog[] = "prog1";
90+
char *args[] = {"prog1", "arg1", "arg2", NULL};
91+
92+
execvp(prog, args);
93+
```
94+
95+
!!! exercise text choice
96+
Qual é o valor de `argc` e `argv` passado para `prog1`?
97+
98+
- [ ] `argc=1, argv={"prog1"}`
99+
- [x] `argc=3, argv={"prog1", "arg1", "arg2"}`
100+
- [ ] `argc=2, argv={"arg1", "arg2"}`
101+
- [ ] `argc=4, argv={"prog1", "arg1", "arg2", NULL}`
102+
103+
!!! answer "Resposta"
104+
Serão três argumentos!
105+
106+
!!! note "Em caso de dúvidas consulte o manual (`man`)"
107+
Caso tenha dúvidas, lembre-se do comando `man`. Explore o manual do `execvp` com:
108+
<div class="termy">
109+
110+
```console
111+
$ man 3 execvp
112+
```
113+
114+
</div>
115+
116+
!!! warning
117+
Os dois próximos exercícios você começar o programa do zero (vazio), pois adaptar exemplos anteriores, apesar de prático, atrapalha a memorização dos comandos usados.
118+
119+
!!! note "Executando programas fora do `PATH` do sistema"
120+
Nos exemplos de **exec**, supomos que os programas a serem executados estavam no **PATH** do sistema. Caso você queira subir algum executável que está na própria pasta do seu projeto (ou em qualquer caminho fixo/relativo conhecido), utilize algo como (**lembre do `./`**):
121+
122+
```C
123+
// Lembre de usar "./" neste caso
124+
char *args[] = {"./meuprograma", NULL};
125+
if (execvp(args[0], args) == -1) {
126+
perror("execvp failed!");
127+
exit(EXIT_FAILURE);
128+
}
129+
```
130+
131+
!!! note "Várias formas de chamar `exec`"
132+
No manual, percebemos que temos várias chamadas de exec: `execl`, `execlp`, `execle`, `execv`, `execvp` e `execvpe`.
133+
Releia prestando atenção nas diferenças.
134+
135+
Aqui, um auxílio de IA será útil! Abra o link https://chatbot.theb.ai/ e faça perguntas como:
136+
137+
`"whats the difference between C functions execv and execvp?"`.
138+
139+
Solicite exemplos e valide códigos!
140+
141+
!!! exercise
142+
Crie um programa `eh_par` que recebe um inteiro como argumento de linha de comando e cujo `main` retorne 1 se o número for par, 0 caso contrário e -1 se ele for negativo.
143+
144+
**Dicas**:
145+
146+
* pesquise a função `atol` para fazer a conversão do argumento de linha de comando para `long`.
147+
* você pode testar seu programa no terminal: basta rodar `eh_par 10` para checar se o número 10 é par.
148+
* para ver o valor de saída do último programa rodado execute `echo $?`
149+
* crie um arquivo `eh_par.c` e compile para `eh_par`
150+
151+
152+
Vamos agora juntar `fork`, `wait` e `exec` em um único exercício!
153+
154+
!!! exercise
155+
Crie um programa que recebe números via `scanf`, executa `eh_par` em um processo filho e usa seu valor de retorno para decidir se o número é par ou não. Seu programa deverá parar de receber números quando `eh_par` retornar -1.
156+
157+
**Dica**: você pode usar `sprintf` para converter o inteiro lido para string. Se não souber como usar consulte o manual executando `man sprintf` no terminal.

content/aulas/14-exec/slides.pdf

982 KB
Binary file not shown.

content/entregas.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Cada tarefa detalha como sua submissão deve ser feita. Geralmente, basta enviar
1616
| 19/03 | Atv07-arrays | Github | 23/03 23h59 |
1717
| 06/04 | Atv08-malloc | Github | 13/04 23h59 |
1818
| 09/04 | Atv09-TAD | Github | 13/04 23h59 |
19-
<!--| 13/10 | Atv10-processos | Github | 19/10 23h59 |
20-
| 16/10 | **Lab02-processos** | Github | **10/11 23h59** |
19+
| 16/04 | Atv10-processos | Github | 23/04 23h59 |
20+
<!--| 16/10 | **Lab02-processos** | Github | **10/11 23h59** |
2121
| 16/10 | Atv11-entrada-saida | Github | 27/10 23h59 |
2222
| 27/10 | Atv12-threads | Github | 03/11 23h59 |
2323
| 03/11 | Atv13-barrier | Github | 07/11 23h59 |

0 commit comments

Comments
 (0)