Post

Como um programa aloca memória? VirtualAlloc, mmap e malloc

Como um programa consegue mais memória do sistema operacional?

Em alguns casos veremos sobre malloc ou calloc, contudo, internamente ele faz algumas coisas. Vejamos:

Sempre que precisamos de mais memória, o que a grande maioria faz é usar o malloc() Contudo, precisamos antes mesmo entender como malloc funciona.

A memória é separada entre a stack (no topo), algumas libraries (no meio) e o heap/globals/source-code (embaixo).

Esse espaço é bem grande se for uma máquina 64 bits == 17 bilhões GB de memória (mais do que temos de fato, mas que poderiamos ter).

Esse espaço, é um espaço de endereços virtuais que uma máquina pode usar para ler/escrever em conjunto com o hard drive e a CPU fará o mapeamento para a memória física. Ou seja, aqui estamos falando de memória virtual.

Retomando… entre o heap e os demais, há uma linha que define o limite que podemos alocar chamada de “Program Break”. Essa linha pode subir ou diminuir, permitindo alocarmos mais memória dinamicamente com malloc. Se você tentar ler/escrever abaixo do Program Break, ok. Caso contrário, segmentation fault!

Sempre que um malloc() é invocado ele chama uma função: brk() que irá subir ou descer o ProgramBreak, permitindo, que o nosso programa tenha mais memória para acessar. Agora, em alguns casos como alocar 5mb ou mais, uma outra função é chamada: o mmap().

mmap() é onde a mágica acontece (seu equivalente ao Windows é o VirtualAlloc).

mmap() é semelhante ao brk(), ele irá solicitar ao kernel mais memória no espaço de endereços para nós. Mas ele faz mais do que aumentar e diminuir o ProgramBreak, ele também permite definir regras de como será acessado aqueles espaços de endereços como privado, read-only, etc. Também podemos especificar o tamanho (quantas páginas vamos alocar).

Também podemos alocar arquivos em memória com os dois últimos parâmetros do mmap(). Outro detalhe é que podemos especificar um ponto de endereço base (baseAddress) para alocar nossos dados.

Nota: O espaço virtual de endereços são definidos em páginas de 4096 bytes cada. Logo, mesmo que solicitamos tamanhos diferentes de 4k, ele irá nos fornecer páginas que caibam 4k.

Resumindo, é assim que alocadores de memórias como malloc() funcionam. Eles solicitam espaços de endereços ao kernel que são espaços paginados em 4k e podem subir ou baixar o ProgramBreak. Contudo, o mmap(), diferente do malloc(), permite especificar um endereço base para gravar nossos dados e mais privilégios de acesso aos endereços.

De fato, seria difícil construir nosso próprio alocador de memória pois teriamos que trabalhar com o brk(). A alternativa quando precisamos de um grande bloco de memória, semelhante ao que vamos usar no jogo, seria trabalhar com alocação virtual mmap(). Ele pode fazer o trabalho melhor do que malloc porque o nosso próprio alocador de memória poderá coexistir com o alocador do sistema sem problemas e teremos controle sobre esse alocar e seus endereços.

Esta postagem está licenciada sob CC BY 4.0 pelo autor.