terça-feira, 19 de junho de 2012

Fork e Thread


Evite o fork() em caso de multithread...

Em sistemas Unix e Unix-like, quando uma chamada de sistema cria um fork, o processo faz uma cópia de si mesmo que chamamos de processo filho (child process). O SO pode diferenciar um do outro pelo retorno da função fork() que é zero no processo filho, enquanto que retorna o PID do processo filho no processo pai.

Quando vários processos rodam concomitantemente no mesmo processador, o kernel do SO pode dividí-los em unidades de processamento que podem ser agendadas segundo uma multiplexação por fração de tempo (time-slice multiplexing). Estas unidades são chamadas de threads de um processo. Processos podem rodar várias threads concorrentemente (multithread process) que otimiza a utilização da memória. Threads de um processo podem compartilhar recursos e memória, o que dois processos não podem fazer, por terem address space diferentes.

A maneira como o SO lida com os processos depende de como o processo foi programado e como ele realiza as chamadas de sistema (system call). Quando dois processos iguais correm em um mesmo sistema Unix, o kernel faz o fork() do processo e cria um novo processo (processo filho) com um novo address space. Além disso, o fork precisa do IPC (InterProcess Comunication) para trocar informações entre o processo pai e o processo filho, depois do fork. [1]

Alternativamente, o SO pode usar o recurso de múltiplos threads de um mesmo processo. Isto é mais vantajoso porque a comunicação e compartilhamento de recursos entre as threads é mais fácil (por estarem no mesmo address space) [2].

Existe, porém, um problema decorrente da chamada de um fork() em um processo multithread. Por exemplo, em um processamento multitarefa um fork() registra no processo pai o PID do processo filho. Mas, quando um thread em uma tarefa multithread executa um fork() qual delas conteria o processo filho? Se bem que é uma situação evitada sempre que possível, existem situações onde o fork do processo multithread resulta no processo filho (também multithread) e o término do processo filho precisa retornar informação para o processo pai via IPC.

Bem, pode ser que o processo filho contenha um thread correspondente ao thread do processo pai. Ou, talvez, é possível igualar o número de threads do processo filho ao do processo pai de tal forma que haja correspondência dos threads.http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

Mas, antes de implementar um fork() em um processo multithread, é preciso planejar muito bem. Normalmente, o processo "forked" deve ser criado como uma única thread e, se um processo multithreaded chama a função fork(), o novo processo deve ser um réplica exata de todas as  threads, bem como de seu espaço de endereçamento.

Por isso,  Pense duas vezes [3] antes de misturar fork() e threads.

Referências:

[1] Stevens, W. R. Unix Network Programming, 2nd Ed., Vol. 1, Prentice Hall, NJ, 1998.

[2] Stevens, W. R. Advanced Programming in the Unix Environment, Addison-Wesley, Reading, Mass., 1992

[3] http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

Um comentário: