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 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.
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.
fonte
fork()
chamada./proc/self/pagemap
determinar 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.O Linux faz Copy-on-Write. Conforme
fork
cria 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.fonte