Forking de processos
Vamos começar com um exemplo simples que imprime "Hello" na saída padrão:
Primeiro passo é compilar o arquivo para um executável do SO:
Após isso, rodamos o executável e:
Dica: se quiser executar tudo em uma linha apenas, pode-se utilizar "gcc forking.c -o forking && ./forking"
So far, so good.
O primeiro fork
Para fazer forking de processos em C, precisamos usar a syscall fork através do cabeçalho unistd.h
(UNIX Standard), que fornece acesso a syscalls do Kernel, permitindo interagir diretamente com o sistema operacional:
E por quê vemos agora a mensagem sendo impressa duas vezes? O quê acontece quando chamamos fork? Vamos detalhar o fluxo do programa:
o processo pai é iniciado no começo do programa; apenas o pai está em execução
quando o
fork
é chamado, o sistema cria um novo processo filho, que é uma cópia exata do processo pai, incluindo o estado do programa naquele exato momentoqualquer código depois do fork é executado tanto no processo pai quanto no processo filho; como ambos chamam a função "printf" com "Hello", então a mensagem é impressa 2 vezes
Um ponto a destacar aqui é que, no momento do fork, todos os file descriptors do pai (incluindo o STDOUT) foram herdados pelo filho, e é por isso que vemos a mensagem na mesma saída padrão (tela do terminal) 2 vezes.
É possível fazer com que o filho tenha outra saída padrão diferente do pai, mas não vamos entrar nestes detalhes aqui, não importam muito para o assunto principal que é concorrência
Se quisermos que cada um imprima uma mensagem diferente, teríamos que saber , de alguma forma após a chamada do fork, se estamos dentro do processo pai ou do filho.
Manual, o nosso melhor amigo
De acordo com o manual, a syscall fork tem o seguinte retorno:
Ou seja, dentro do filho, o retorno da função é 0
. E dentro do pai, o retorno é o PID do filho. Com isto, podemos ter o seguinte código:
Que se executado, tem a seguinte saída:
Yay!
Mas repare que, devido à natureza preemptiva do escalonador, não temos controle sobre qual será executado primeiro. Poderia ser o pai, ou mesmo o filho.
O que temos que entender aqui é que, no momento do fork, é criado um novo processo no sistema operacional, que irá competir por recursos junto a outros processos, ou seja, todo mundo junto no mesmo balaio de concorrência.
Um exemplo mais robusto
Agora, vamos a um exemplo um pouco mais robusto com o uso de fork de processos, onde um processo pai dispara 3 processos filhos que irão executar uma tarefa que demora 2 segundos cada:
Interessante notar aqui:
os 3 processos filhos foram criados e iniciaram sua execução (271052, 271053, 271054)
2 processos terminaram um pouco antes, sendo que o processo pai notificou que ambos tinham concluído execução
um último processo (271054) terminou depois que o pai tinha notificado sobre os outros dois que concluíram primeiro
o pai informa que todos os filhos foram concluídos e o programa finaliza
Isto, senhoras e senhores, é a maravilha da concorrência. Não temos controle algum sobre a ordem e execução das tarefas!
Sim, vou repetir isso inúmeras vezes neste guia kk
Comunicação entre processos (IPC)
Como processos não compartilham memória (a priori), precisamos de um mecanismo de comunicação entre processos, também chamado de IPC (Inter-process communication), pois um processo sem comunicação é bastante inútil.
Uma das formas de IPC é através de pipes, que são uma comunicação uni-direcional entre processos.
Se você quer entender mais sobre IPC e UNIX pipes, escrevi um artigo sobre o tema, onde é possível aprofundar nos conceitos de forma prática, e você só precisa de um terminal com shell/bash ou outra shell de preferência
Este é um exemplo bastante simples de como 2 processos distintos podem conversar entre si, através da utilização de UNIX pipes.
Tá gostando do guia?
Se está gostando deste trabalho e considera fortalecer, o QRCode de PIX abaixo tá no jeito hein?
Ou copia a cola:
Não vamos entrar em mais detalhes sobre uso de forking em C, isto já é o suficiente para o objetivo deste guia. No próximo tópico, iremos abordar o uso de threads em C.
Last updated