Vous êtes sur la page 1sur 9

UNIVERSIDADE FEDERAL DO RIO DE JANEIRO

MAB366 – SISTEMAS OPERACIONAIS


PERÍODO 2008/1

SISTEMAS
OPERACIONAIS
Trabalho 2 – Estudo e aplicação de subprocessos

Integrantes

André Mendes de Oliveira Paiva


André Ramos Fernandes da Silva
Diego Marin Santos
Marcelo Rezende Bueno
Thiago Sabatucci da Silva
ÍNDICE
Α) ESTUDO E DESCRIÇÃO DOS COMANDOS

fork()  
......................................................................................................................................................3
exec() .....................................................................................................................................................3
execl() ....................................................................................................................................................3
wait() .....................................................................................................................................................3
exit() ......................................................................................................................................................4
getpid() ..................................................................................................................................................4
getppid() ................................................................................................................................................4
Β) EXECUTE O PROGRAMA (PROG1) EM ANXO EM UM AMBIENTE LINUX E RESPONDA ÀS
SEGUINTES PERGUNTAS

b1) Qual o retorno esperado de cada um dos comandos fork() e do comando execl()? ......................4
b2) No caso do presente código, qual a resposta correta para o comando: printf(“Resultado: o  
comando foi/não foi executado com sucesso\n”)? ................................................................................4
b3) A identificação do processo pai (PID) será sempre maior ou menor que a dos processos filho?  
Justifique. ..............................................................................................................................................4
b4) identificação (PID) é sempre atribuída de forma seqüencial ou pode ser aleatória? Justifique.  
..5
b5) Em quantos processos resulta a execução deste programa? Quais são eles? Que parte do código  
cada um executa? ..................................................................................................................................5
b6) Qual No segundo fork(), responda as perguntas de quem sou eu e informe quem é o processo pai  
de cada um deles. ..................................................................................................................................5
b7) Qual a finalidade do comando wait()? Que valores ele pode retornar? ........................................5
b8) Para que serve a variável status? Que valores ela pode receber e o que eles significam?............5
b9) O comando printf() seguinte ao comando execl() é geralmente executado ou não? Apresente suas  
conclusões para tal comportamento. ....................................................................................................5
b10) Para os possíveis casos de 9, como funcionaria o comando exit()? ............................................6
b11) Altere o comando execl() para executar corretamente o comando “pwd” e discuta o resultado  
global da execução.  
...............................................................................................................................6
Χ) EXECUTE O PROGRAMA (PROG2) EM ANEXO EM UM AMBIENTE LINUX E RESPONDA ÀS
SEGUINTES PERGUNTAS:

c1) Monte e mostre a árvore genealógica da família de processos. .....................................................6
c2) Execute o programa por algum número de vezes, verifique a dinâmica e a ordem em que as  
coisas acontecem. Quais suas conclusões?  
...........................................................................................6
c3) Aumente para 3 o número de “maxsubprocs” e monte novamente a árvore genealógica da  
família. Dê uma justificativa para a nova estrutura da árvore. ............................................................6
c4) Para que serve a variável “j”? .......................................................................................................6
c5) Substitua Substitua a instrução “for (i = j; i < maxsubprocs; i++)” por “for (i = 0; i <  
maxsubprocs; i++)” e veja o que acontece. Descreva e Justifique o ocorrido. ...................................6
c6) Verifique o valor das variáveis vistas por cada processo e explique como funciona o escopo das  
mesmas. .................................................................................................................................................6
2
c7) Mova a declaração da variável “dado2” para dentro da rotina main() e compare os resultados  
com os obtidos em c.6. ..........................................................................................................................6
∆) PROCESSOS COOPERATIVOS

d1) Experimento 1 .................................................................................................................................7
d2) Experimento 2. ................................................................................................................................7

a. Estudo e Descrição de Comandos

   •   Descreva os comandos: fork(); exec(); execl(); wait(); exit(); getpid() e getppdi().

fork()
Este comando é a única chamada de sistema que possibilita a criação de um
processo em UNIX. Os processos pai e filho partilham o mesmo código. O segmento
de dados do usuário do novo processo (filho) é uma cópia exata do segmento
correspondente ao processo antigo (pai). Por outro lado, a cópia do segmento de
dados do filho do sistema pode diferir do segmento do pai em alguns atributos
específicos (como por exemplo, o pid, o tempo de execução, etc.). Os filhos
herdam uma duplicata de todos os descritores dos arquivos abertos do pai (se o
filho fecha um deles, a cópia do pai não será modificada). Mais ainda, os
ponteiros para os arquivos associados são divididos (se o filho movimenta o
ponteiro dentro de um arquivo, a próxima manipulação do pai será feita a partir
desta nova posição do ponteiro). Esta noção é muito importante para a
implementação dos pipes (tubos) entre processos.
Tem como valores de retorno 0 para o processo filho, e o identificador do processo filho para o 
processo pai; e ­1 em caso de erro, pois o sistema suporta a criação de um número limitado de 
processos. 

exec()
O comando exec() troca o processo corrente pelo novo que foi especificado. Se a
função retorna, um erro terá ocorrido. O valor de retorno é -1 neste caso, e a
variável global errno será setada para indicar o erro.

execl()
O comando execl() significa execute and leave, ou seja, executa e termina o
comando indicado pelo pathname com as opções indicadas pelos restantes
argumentos da função. Este comando requer que cada um dos argumentos da linha de
comando passada ao novo programa seja especificada por argumentos em separado. O
último argumento é o NULL pointer. Assim como exec(), se a função retorna, um
erro terá ocorrido. Neste caso, o valor de retorno é -1, e a variável global
errno será setada para indicar o erro.

3
wait()
A função wait suspende a execução do processo até a morte de seu filho. Se o filho já estiver 
morto no instante da chamada da primitiva (caso de um processo zumbi), a função retorna 
imediatamente. Os possíveis valores de retorno são o identificador do processo morto ou ­1 em caso 
de erro. 

exit()
O comando exit() provoca o término do programa em execução. Este
comando não retorna nenhum valor.

getpid()
O comando getpid() retorna o identificador do processo corrente.

getppid()
O comando getppid() retorna o identificador do processo pai do
processo corrente.

b. Execute o programa (prog1) em anexo em um ambiente LINUX e responda às seguintes 
perguntas:

b.1 Qual o retorno esperado de cada um dos comandos fork() e do comando execl()?

O valor esperado de ambos os comandos fork() são 0  para o processo criado recentemente, 
isto é, o processo filho e também o  identificador do processo filho para o processo pai, cujo valor 
pode ser obtido  através do comando getpid(). O valor esperado do comando execl(), se houver 
retorno, será ­1, indicando que um erro terá sido ocorrido.

b.2 No caso do presente código, qual a resposta correta para o comando:

         printf(“Resultado: o comando foi/não foi executado com sucesso\n”)?

 Resultado: o comando não foi executado com sucesso,

4
b.3 A identificação do processo pai (PID) será sempre maior ou menor que a dos processos 
filho? Justifique.

A identificação do processo pai será sempre menor que a dos processos filho, pois os 
identificadores dos processos filho são normalmente gerados sequencialmente, o que implica que 
um processo gerado mais recentemente, no caso o processo filho, não possa ter seu identificador 
maior que a do seu pai.

   

b.4 A identificação (PID) é sempre atribuída de forma seqüencial ou pode ser aleatória? 
Justifique.

A identificação (PID) é normalmente gerada de forma seqüencial, pois só pode haver um processo 
rodando na CPU e existem vários outros processos nas filas, o que faz com que eles recebam 
números seqüenciais.

b.5 Em quantos processos resulta a execução deste programa? Quais são eles? Que parte do 
código cada um executa?

A execução deste programa resulta em 3 processos. Um processo é o que estava sendo executado e 
os outros 2 são criados através dos comandos fork(). O primeiro  processo executa o bloco else mais 
externo e depois o bloco else interno. O segundo processo executa o bloco else dentro do bloco if  
mais externo ao passo que o terceiro processo, executa o bloco if dentro do bloco if mais externo.

b.6 No segundo fork(), responda as perguntas de quem sou eu e informe quem é o processo pai 
de cada um deles.

Quem sou eu é o processo criado menos recentemente, logo será o FILHO, ao passo que E eu quem  
sou será o processo criado mais recentemente, que nesse caso será o NETO.

b.7 Qual a finalidade do comando wait()? Que valores ele pode retornar?

A finalidade do comando wait() é suspender a execução do processo corrente até que a execução do 

5
seu filho seja terminada. Ele pode retornar o identificador do processo que mudou seu estado.

b.8 Para que serve a variável status? Que valores ela pode receber e o que eles significam?

A variável status serve para informar ao processo principal o status de término do filho através de 
seus bits setados. Ela pode receber 0 ou 1, sendo que 0 significa que o filho terminou com sucesso e 
1 caso contrário.

b.9 O comando printf() seguinte ao comando execl() é geralmente executado ou não? 
Apresente suas conclusões para tal comportamento.

O comando printf() seguinte ao comando execl()  não é geralmente executado mesmo que o 
comando execl() retorne ­1, indicando algum erro.

b.10 Para os possíveis casos de 9, como funcionaria o comando exit()?

O comando exit() ativa o wait que o pai faz, encerrando o neto com um estado anômalo. Nesse caso, 
o exit() avisa que o pai deve imprimir na tela um aviso ao usuário dizendo que o comando execl() 
não foi executado e que o neto foi finalizado com erro.

b.11 Altere o comando execl() para executar corretamente o comando “pwd” e discuta o 
resultado global da execução.

execl ("/bin/pwd","pwd",0);

O comando execl() foi alterado para executar o comando pwd, que lista o diretório corrente da 
aplicação. A imagem do processo foi alterada pela do processo pwd (o path da execução do 
programa carregado por execl encontra­se no primeiro argumento de chamada da função), o 
comando pwd executado, o processo finalizado e a imagem original do processo filho restaurada.

c. Execute o programa (prog2) em anexo em um ambiente LINUX e responda às seguintes 
perguntas:

6
c.1 Monte e mostre a árvore genealógica da família de processos.

c.2 Execute o programa por algum número de vezes, verifique a dinâmica e a ordem em que 
as coisas acontecem. Quais suas conclusões?

Na maioria das vezes, ocorre a criação de um processo pai a partir do processo principal (Init), 
seguida da criação do primeiro processo filho desse pai, criação de um neto a partir do primeiro 
filho gerado e finalmente a criação do segundo processo filho.

c.3 Aumente para 3 o número de “maxsubprocs” e monte novamente a árvore genealógica da 
família. Dê uma justificativa para a nova estrutura da árvore.

c.4 Para que serve a variável “j”?

c.5 Substitua a instrução “for (i = j; i < maxsubprocs; i++)” por “for (i = 0; i < maxsubprocs; 
i++)” e veja o que acontece. Descreva e Justifique o ocorrido.

7
c.6 Verifique o valor das variáveis vistas por cada processo e explique como funciona o escopo 
das mesmas.

c.7 Mova a declaração da variável “dado2” para dentro da rotina main() e compare os 
resultados com os obtidos em c.6.

d. Processos Cooperativos

d.1) Experimento 1

   Construa uma aplicação utilizando o conceito de processos filhos de forma a atender os 
seguintes requisitos:

          P1 possui um Loop para gerar 5 números aleatórios entre 5 e 25. Para cada número par 
gerado cria um subprocesso P2 e envia o número para ele; para cada número ímpar cria um 
subprocesso P3 e envia o número para ele. P3 calcula a série de Fibonacci com o valor do 
número recebido e envia o resultado a P1; P4 calcula a permutação com o valor do número 
recebido e envia o resultado a P1; P1 mostra os resultados recebidos: a classificação feita se 
par ou ímpar, a operação realizada (Fibonacci ou Permutação) e o resultado recebido do 
processo que realizou o cálculo.

d.2) Experimento 2

   Construa uma aplicação utilizando o conceito de processos filhos de forma a atender os 
seguintes requisitos:

          P1 possui duas matrizes, uma de 1x5 e outra de 5x8 valores inteiros e precisa calcular o 
produto das mesmas. P1 gera suprocessos de forma a paralelizar a execução, cada um realiza 
o cálculo de um dos produtos; Ao final P1 apresenta a matriz resultado.

8
9