domingo, 6 de dezembro de 2015

Hardcore Devel #43 - Fork

Desenvolver é uma coisa complicada.


E fica ainda mais quando a gente precisa colocar garfos na coisa.

Fork traduzido para português vira garfo. Em um contexto de direção pode significar uma bifurcação. Quando a gente ta falando de programação a gente ta falando em gerar um processo paralelo. Pelo menos quando a gente está programando em C ou C++.

Pois é. A programação paralela esta aí e está resolvendo muitos problemas, e continua resolvendo muitos outros. Muitas coisas em dia utilizam programação paralela porque as vezes o programa não precisa ficar parado esperando alguma coisa acontecer para poder continuar. É aí que o fork entra.

O Fork é uma função que pertence a uma das bibliotecas do Unix. E ele é o responsável por ceder o poder da programação paralela a aqueles que programam na linguagem mãe desess sistemas. Java tem um jeito completamente diferente de tratar programação paralela, a qual não iremos cobrir aqui. Vamos falar só do nosso garfinho mesmo.

O que temos pra falar dele? Bom, vamos fazer um código exemplo em C++ aqui pra tentar dar uma clareada.

#include<iostream>
using namespace std;

int main() {
  int a, b;
  a = 5;
  b = 5;
  cout << a << endl;
  a = fork();
  cout << "Fork " << a << " " << b << endl;
  return 0;
}

Vamos começar logo do ponto estranho.
a = fork(); //????????

Pois é. O fork() retorna um inteiro. Na verdade o fork retorna dois inteiros porque ele vai retornar um para o processo corrente e outro para o processo criado. O processo que foi criado vai ter o valor de retorno 0. Enquanto o processo corrente ganha o identificador do processo que foi gerado. Chamamos eles de processo pai e processo filho.

Ok, ele cria um outro processo, mas qual vai ser o código do outro processo a ser criado? O que o outro processo vai fazer? Ninguém falou nada até agora!

Na verdade, ambos vão seguir o fluxo de código apresentado a partir do ponto onde ocorreu o fork, que mais especificamente é esse aqui:

a = fork();

Os dois processos vão dar algum valor para a variável a. Só que já vimos que o processo filho vai dar o valor 0 e o processo pai vai ganhar o identificador do fiilho. E ambos vão terminar de executar o resto do código.

cout << "Fork " << a << " " << b << endl;
return 0;

Ou seja, os dois vão imprimir "Fork " e algum número e o 5. O processo filho certamente irá imprimir "Fork 0 5", não da pra prever qual vai ser o identificador que o processo pai vai ganhar.


- Ah, mas e o resto do código que tem antes?

O resto do código que tem antes é ignorado. Simples assim. Tudo o que acontece antes do fork acontece quase que exclusivamente para o processo pai. Então certamente tudo aquilo que ele pediu para imprimir antes de disparar um novo processo não será reimpresso.

Eu disse quase.

Algumas coisas curiosas acontecem com as variáveis. Você notou que eu não declarei nenhuma variável nova para o processo filho, certo? Isso é porque o processo filho recebe variáveis com os mesmos nomes do processo pai. É ainda mais profundo. A variável é passada com um valor já definido, e esse valor é herdado do processo pai! Lembra que eu falei o que o processo filho ia imprimir. Notou que eu afirmei que ele ia imprimir o 5 depois do 0? A variável vem com o valor copiado do pai!

E o que é melhor, arquivos em Unix são números inteiros, que também são chamados de File Descriptors. E os processos compartilham o acesso a arquivos. Então tome cuidado se estiver compartilhando um mesmo arquivo entre diversos processos.

Acho que isso é tudo que você precisa para encarar o Fork de peito aberto, mas definitivamente não é tudo sobre programação paralela!

Nenhum comentário:

Postar um comentário