Quando um processo forks é copiado sua memória virtual ou residente?

12

A maneira padrão de fazer novos processos no Linux é que o footprint de memória do processo pai é copiado e se torna o ambiente do processo filho até que execv seja chamado.

De que pegada de memória estamos falando, o virtual (o que o processo solicitou) ou o residente (o que realmente está sendo usado)?

Motivação: Eu tenho um dispositivo com espaço de troca limitado e um aplicativo com uma grande diferença entre o consumo de memória virtual e residente. O aplicativo não pode bifurcar devido à falta de memória e gostaria de ver se tentar reduzir o tamanho do footprint virtual ajudaria.

    
por TheMeaningfulEngineer 01.06.2015 / 14:20

3 respostas

12

Nos sistemas modernos, nenhuma da memória é realmente copiada apenas porque uma chamada do sistema fork é usada. Tudo é marcado como somente leitura na tabela de páginas, de modo que, na primeira tentativa de escrever uma armadilha no código do kernel, isso acontecerá. Somente quando o primeiro processo tentar escrever, a cópia acontecerá.

Isso é conhecido como copy-on-write.

No entanto, pode ser necessário acompanhar também o espaço de endereço confirmado. Se nenhuma memória ou troca estiver disponível no momento em que o kernel tiver que copiar uma página, ele terá que matar algum processo para liberar memória. Isso nem sempre é desejável, portanto, é possível manter o controle da quantidade de memória com a qual o kernel se comprometeu.

Se o kernel for submetido a mais do que a memória + troca disponível, ele pode fornecer um código de erro na tentativa de chamar fork. Se houver bastante disponível, o kernel se comprometerá com o tamanho virtual completo do pai para ambos os processos após a bifurcação.

    
por 01.06.2015 / 14:45
5

Não se preocupe, ele faz uma cópia preguiçosa (copy-on-write). Os endereços de memória virtual de ambos os processos apontam para as mesmas páginas inicialmente, mas quando o processo bifurcado tenta modificá-lo, ele realmente faz uma cópia física da página (a partir de então, essa página reside em dois lugares na sua RAM). / p>

Cuidado, nenhuma das pegadas de memória informadas realmente informa quanto da RAM o processo está usando. Por causa de troca, compartilhamento de memória e outros problemas com a memória virtual, é impossível saber com certeza. Algumas partes do espaço da memória são bibliotecas compartilhadas (onde contá-las?), Algumas referem-se à memória não-RAM (outros dispositivos de hardware), algumas estão atualmente trocadas, algumas não são copiadas ainda (copy-on-write) e em breve. Leia isto:

link

    
por 01.06.2015 / 14:45
5

Existe configuração do kernel

/ proc / sys / vm / overcommit_memory

Citação do excelente artigo :

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

Isso se aplica a garfos e a um malloc comum. Ou seja se você defini-lo como 0, o fork será copiado na gravação. Copiar em gravação significa que, uma vez que o aplicativo seja bifurcado, ambas as cópias compartilharão as páginas de memória. O utilitário child ou original iniciará a alteração da memória.

Na maioria das distribuições eu sei overcommit é 0. Mas se você definir para 2, todas as páginas de memória serão totalmente apoiadas por memória real e em alguns casos sob alta pressão de memória será mais estável, mas alguns programas (eu enfrentei gitk ) que dependem de overcommits irão falhar.

    
por 01.06.2015 / 15:07