Vous êtes sur la page 1sur 13

O que faz um fork ()?

Julho 2014

...ou o pequeno fork() ilustrado....

Introduo
Execuo do papai
O fork
Controlar a execuo do pai e do filho
As variveis e os descritores de arquivos
Sincronizao
Fim
Notas e agradecimentos

Introduo
Um "fork" uma caracterstica dos sistemas Unix ou Linux para duplicar um processo. Para
explicar como funciona, vamos partir de um processo que chamaremos, carinhosamente, de
"papai". Este processo vai simplesmente se duplicar e os dois processos (pai e filho) mostraro
a cada um os seu status (pai ou filho).

Execuo do papai
Vamos partir de um processo pai. , A fim de identificar claramente as questes do fork (garfo),
tambm vamos observar seus descritores de arquivos, ou melhor, um dos mais importantes: o do
fluxo de sada (stdout), ou seja, a tela. Vamos tambm colocar-lhe uma pequena varivel global
que ser usado posteriormente para indicar o estado do processo (pai ou filho). Veja como ficar
o nosso processo inicial:

O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = NULL;

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork();
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

A seta vermelha aponta para a prxima instruo a ser executada. Como ainda no executamos
nada, estamos no comeo do main. Ento, vamos executar as duas primeiras instrues:
O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork();
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

Podemos ver em vermelho as instrues que foram executadas, assim como os dados que
foram modificados pela ltima declarao. At aqui tudo bem, vamos mudar o valor do
quemsoueu para atribuir-lhe a identidade do pai. Passemos para a prxima instruo.

O fork
A prxima instruo a mais difcil de entender, vamos execut-la e ver o que acontece.
O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 1000
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

O FILHO

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 0
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}
O pai chamou o garfo e se duplicou. Isto implica vrias coisas:

Um novo processo foi criado, ele considerado como o filho do processo que chamou o
fork()
Este processo uma cpia fiel do seu pai. Alis, a prxima instruo a ser executada ser
a mesma para ambos: a condio "if".
A funo fork() no retorna a mesma coisa para ambos os processos. Para o filho, ele
retornar o 0. Para o pai, ele retornar o pid do filho (seu nmero de processo).
Esta duplicao envolve algumas coisas sobre as variveis e os descritores de arquivos.
Vamos chegar l.

Passemos instruo seguinte para os dois.

Controlar a execuo do pai e do filho


O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 1000
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

O FILHO

Descritores de arquivos
1: (Stdout) Posio = 0

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 0
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}
Ambos os processos acabaram de verificar a condio if. J que no pai, a varivel pid ser
diferente de 0, ele continuar no else. Em compensao, o filho entrar no bloco do "if" pois,
para ele, o pid igual a 0. Importante: assim ento, que controlaremos a execuo do pai e
do filho: verificando o valor da varivel pid, que diferente para ambos. Vamos continuar.

As variveis e os descritores de arquivos


O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 15

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 1000
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

O FILHO

Descritores de arquivos
1: (Stdout) Posio = 15

Variveis globais
const char* quemsoueu = "O filho";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 0
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}
Ateno, este ponto no pode ser negligenciado!

O filho mudou o valor da sua varivel quemsoueu. Isso mudou o valor de sua prpria
varivel quemsoueu, mas no a do pai. Veja ento a nossa primeira concluso: as
variveis do pai e do filho so inteiramente distintas; mesmo que tenham o mesmo
nome, no so as mesmas variveis. Por outro lado, voc notar que no momento do
"fork", o filho tinha herdado os valores de todas as variveis do seu pai.
O pai acabou de fazer um printf e, consequentemente, escreveu: "Eu sou o pai" no fluxo de
sada padro (stdout). Assim, aps este registro, o ponteiro do arquivo stdout aumentou
para 15 caracteres (o comprimento da frase exibida). Voc j reparou que aconteceu o
mesmo com o filho? Na verdade, se, por uma lado, o pai e o filho tm variveis
distintas, por outro, os seus descritores de arquivos so os mesmos . Ento, se um
dos dois processos muda o seu ponteiro de posio em um arquivo, isso tambm ser
refletido no outro. Ateno, isso s vlido para os descritores de arquivos herdados
durante o fork. Se o pai ou o filho abrirem outros arquivos aps o fork, esses descritores
no sero compartilhados entre eles. Da mesma forma, se o filho fecha um descritor de
arquivo herdado do pai, o descritor de arquivo do pai no ser fechado (idem no sentido
contrrio).

Sincronizao
O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 30

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 1000
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

O FILHO

Descritores de arquivos
1: (Stdout) Posio = 30

Variveis globais
const char* quemsoueu = "O filho";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 0
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}
Quanto ao Filho: um printf foi feito, desta vez para exibir "Eu sou o filho." O ponteiro do
arquivo aumentou ara 15 no filho, o que se reflete no pai.
Quanto ao Pai: o pai executou a funo wait(). Esta funo permite a sincronizao entre o
pai e todos os seus filhos. Isto significa que o pai vai parar de se executar (neste caso, diz-
se que ele est dormindo) at que seu filho termine completamente.

Fim
O PAPAI

Descritores de arquivos
1: (Stdout) Posio = 30

Variveis globais
const char* quemsoueu = "O PAPAI";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 1000
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}

O FILHO

Descritores de arquivos
1: (Stdout) Posio = 30

Variveis globais
const char* quemsoueu = "O filho";

int main()
{
pid_t pid;
quemsoueu = "O papai";
pid = fork(); //pid = 0
if(pid = = 0){
quemsoueu = "O filho";
printf("Eu sou %s, quemsoueu);
}
else{
printf("Eu sou %s, quemsoueu);
wait(NULL);
}
return 0;
}
O filho acabou de executar a sua ltima instruo, agora ele no existe mais. Durante esse
tempo, o pai ainda estava esperando, mas logo ele ir acordar, j que o filho terminou.
Finalmente, o pai tambm vai acabar.

Notas e agradecimentos
A imagem que precede o sumrio a alterao de uma fotografia original produzida pela
tanakawho. Traduo feita por Lucia Maurity y Nouira
Este documento, intitulado O que faz um fork ()? a partir de Kioskea (pt.kioskea.net) est disponibilizado sob a
licena Creative Commons. Voc pode copiar, modificar cpias desta pgina, nas condies estipuladas pela
licena, como esta nota aparece claramente.

Vous aimerez peut-être aussi