Quando um processo bifurca-se sua memória virtual ou residente é copiada?

12

A maneira padrão de criar novos processos no Linux é que a pegada de memória do processo pai seja copiada e que se torne o ambiente do processo filho até que execvseja chamada.

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

Motivação: tenho um dispositivo com espaço de troca limitado e um aplicativo com uma grande diferença entre a pegada de memória virtual e residente. O aplicativo não pode ser bifurcado devido à falta de memória e gostaria de ver se tentar reduzir o tamanho da área virtual ajudaria.

TheMeaningfulEngineer
fonte

Respostas:

12

Nos sistemas modernos, nenhuma memória é realmente copiada apenas porque uma chamada do sistema fork é usada. Tudo está marcado como somente leitura na tabela de páginas, de forma que, na primeira tentativa de gravar uma interceptação no código do kernel, ocorra. Somente uma vez que o primeiro processo tenta gravar, a cópia acontece.

Isso é conhecido como cópia na gravação.

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 precisará interromper algum processo para liberar memória. Isso nem sempre é desejável, portanto, é possível acompanhar a quantidade de memória que o kernel se comprometeu.

Se o kernel se comprometer com mais do que a memória disponível + swap, poderá fornecer um código de erro na tentativa de chamar o fork. Se estiver disponível o suficiente, o kernel se comprometerá com o tamanho virtual completo do pai para ambos os processos após o fork.

Kasperd
fonte
1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.Sim obrigado. Significando que a redução da área de cobertura virtual do processo em um ambiente com memória limitada (RAM e troca) poderia resolver o problema de não conseguir fazer uma bifurcação.
TheMeaningfulEngineer
1
@ Alan Sim. Se forkfalhar com uma mensagem de erro indicando memória insuficiente. Em seguida, reduzir o uso de memória virtual do processo antes de fazer a bifurcação pode ajudar.
kasperd
5

Não se preocupe, ele faz uma cópia lenta (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 efetivamente faz uma cópia física da página (a partir de então, essa página reside em dois lugares na sua RAM).

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

https://lwn.net/Articles/642202/

orion
fonte
5

Há configuração do kernel

/ proc / sys / vm / overcommit_memory

Citação de 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, bem como malloc regular. Ou seja, se você definir como 0, o fork será copiado na gravação. Copiar na gravação significa que, uma vez que o aplicativo é bifurcado, as duas cópias compartilharão as páginas de memória úteis, ou o original começará a mudar a memória.

Na maioria das distribuições, eu sei que o overcommit é 0. Mas se você o definir como 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ão mais estáveis, mas alguns programas (eu enfrentei o gitk) que dependem em supercomissões falhará.

gena2x
fonte