O fork () copia imediatamente todo o heap do processo no Linux?


30

Uma fork()chamada do sistema clona um processo filho do processo em execução. Os dois processos são idênticos, exceto pelo PID.

Naturalmente, se os processos estiverem apenas lendo seus amontoados, em vez de gravá-los, copiar o heap seria um enorme desperdício de memória.

Todo o heap do processo é copiado? É otimizado de uma maneira que apenas a escrita dispara uma cópia de pilha?

Respostas:


19

A totalidade da fork()é implementado usando mmap / copiar na escrita.

Isso não afeta apenas o heap, mas também as bibliotecas compartilhadas, a pilha e as áreas BSS.

O que, aliás, significa que o fork é uma operação extremamente leve, até que os 2 processos resultantes (pai e filho) realmente comecem a gravar em intervalos de memória. Esse recurso é um dos principais contribuintes para a letalidade de fork-bombs - você acaba com muitos processos antes que o kernel fique sobrecarregado com a replicação e diferenciação de páginas.

Você terá dificuldade em encontrar em um sistema operacional moderno um exemplo de operação em que o kernel executa uma cópia impressa (os drivers de dispositivo são a exceção) - é apenas muito, muito mais fácil e mais eficiente empregar a funcionalidade de VM.

Even execve()é essencialmente "por favor, mapeie o binário / ld.so / whatnot, seguido de execute" - e a VM lida com o carregamento real do processo na RAM e na execução. Variáveis ​​locais não inicializadas acabam sendo mamapedadas de uma 'página zero' - página especial de leitura e gravação somente para leitura contendo zeros, variáveis ​​inicializadas locais acabam sendo mmapedadas (cópia na gravação, novamente) do próprio arquivo binário, etc.


Uma exceção notável são os processos Java. Procure "fork java memory" e você encontrará dezenas de problemas que afetam a JVM de servidor grande ou a JVM incorporada tentando executar um pequeno comando shell e travando miseravelmente em uma exceção "Não é possível alocar memória" (estes são apenas links aleatórios, esse problema é sistêmico para os ambientes Java). Essa resposta do SO acusa o coletor de lixo da JVM e o compilador JIT de impedir que a memória dos processos seja compartilhada.
precisa saber é o seguinte

24

O kernel do Linux implementa o Copy-on-Write quando fork()é chamado. Quando o syscall é executado, as páginas que o pai e o filho compartilham são marcadas como somente leitura.

Se uma gravação é executada na página somente leitura, ela é copiada, pois a memória não é mais idêntica entre os dois processos. Portanto, se apenas operações de leitura estiverem sendo executadas, as páginas não serão copiadas.


1
+1 Obrigado! 1. Você poderia fornecer links de referência? 2. O heap é copiado totalmente ou em partes?
precisa

4
2. - Nas páginas :) O kernel tem muito pouco entendimento do que é "heap" - para o kernel, são apenas várias páginas particulares mmappedadas, que os alocadores da libc manipulam como bem entenderem.
Qdot

Isso é realmente uma bomba de forquilha necessariamente? Parece-me que, em vez de bifurcar o processo atual, esse código criará mais instâncias do mesmo programa que são executadas desde o início, e não da próxima instrução após a fork()chamada.
sherrellbc

@mmk FYI, fiquei bastante surpreso com a sua "Nota lateral interessante:" e por isso testei (no Linux 3.2.0) para ver, e isso não parece ser verdade. Eu costumava /proc/self/pagemapdeterminar o endereço virtual para o mapeamento de página física para o objetivo do teste. Como eu esperava, se o neto e apenas o neto escreverem a página compartilhada, o pai e o filho original continuarão a compartilhá-lo. Somente o neto acaba com uma cópia particular.
Celada

@Celada. Hmm. Eu já tinha lido isso em algum lugar e não me lembro da versão do kernel à qual estava se referindo (provavelmente uma mais antiga?), Portanto, pode não ser mais válida.
Mmk #

10

O Linux faz Copy-on-Write. Conforme forkcria um novo processo, as páginas alocadas são marcadas como somente leitura e compartilhadas entre o pai e o filho. Quando um deles tenta modificar uma página, é gerada uma falha na página, resultando na cópia da página e no ajuste apropriado da tabela de páginas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.