Como o tamanho da pilha e da pilha é limitado pelo sistema operacional?

21

Nota : se você precisar considerar um sistema operacional específico para poder responder, considere o Linux.

Sempre que executo um programa, ele recebe um espaço de memória virtual para executar, com uma área para sua pilha e outra para sua pilha.

Pergunta 1 : a pilha e o heap têm um limite de tamanho estático (por exemplo, 2 gigabytes cada) ou esse limite é dinâmico, mudando de acordo com as alocações de memória durante a execução do programa (ou seja, 4 gigabytes no total a serem usados ​​por ambos, portanto, se um programa usar apenas a pilha, poderá ter uma pilha com 4 gigabytes)?

Pergunta 2 : Como o limite é definido? É a memória RAM total disponível?

Pergunta 3 : E as seções de texto (código) e dados, como elas são limitadas?

Daniel Scocco
fonte
Stack: unix.stackexchange.com/questions/145557/...
Ciro Santilli新疆改造中心法轮功六四事件

Respostas:

23

Existem dois limites de memória diferentes. O limite de memória virtual e o limite de memória física.

Memória virtual

A memória virtual é limitada pelo tamanho e layout do espaço de endereço disponível. Geralmente, no início, está o código executável, os dados estáticos e o passado que aumentam o heap, enquanto no final a área é reservada pelo kernel, antes dele as bibliotecas e pilhas compartilhadas (que na maioria das plataformas crescem). Isso dá ao heap e empilhe espaço livre para crescer, sendo as outras áreas conhecidas na inicialização do processo e corrigidas.

A memória virtual livre não é inicialmente marcada como utilizável, mas é marcada durante a alocação. Embora o heap possa aumentar para toda a memória disponível, a maioria dos sistemas não aumenta automaticamente as pilhas. O limite padrão do IIRC para a pilha é 8MiB no Linux e 1MiB no Windows e pode ser alterado nos dois sistemas. A memória virtual também contém arquivos e hardware mapeados na memória.

Uma razão pela qual a pilha não pode ser aumentada automaticamente (arbitrariamente) é que os programas multiencadeados precisam de uma pilha separada para cada encadeamento, para que acabem atrapalhando um ao outro.

Em plataformas de 32 bits, a quantidade total de memória virtual é 4GiB, Linux e Windows normalmente reservam o último 1GiB para o kernel, fornecendo no máximo 3GiB de espaço de endereço. Existe uma versão especial do Linux que não reserva nada, oferecendo 4GiB completo. É útil no caso raro de grandes bancos de dados nos quais o último 1GiB salva o dia, mas para uso regular é um pouco mais lento devido às recargas adicionais da tabela de páginas.

Nas plataformas de 64 bits, a memória virtual é 64EiB e você não precisa pensar nisso.

Memória física

Normalmente, a memória física é alocada pelo sistema operacional quando o processo precisa acessá-la. Quanta memória física um processo está usando é um número muito nebuloso, porque alguma memória é compartilhada entre processos (o código, bibliotecas compartilhadas e outros arquivos mapeados), os dados dos arquivos são carregados na memória sob demanda e descartados quando há falta de memória e A memória "anônima" (aquela não suportada por arquivos) pode ser trocada.

No Linux, o que acontece quando você fica sem memória física depende da vm.overcommit_memoryconfiguração do sistema. O padrão é confirmar demais. Quando você solicita que o sistema aloque memória, ele fornece algumas informações, mas apenas aloca a memória virtual. Quando você realmente acessa a memória, ele tenta usar alguma memória física, descartando dados que podem ser relidos ou trocando as coisas conforme necessário. Se achar que não pode liberar nada, simplesmente removerá o processo da existência (não há como reagir, porque essa reação poderia exigir mais memória e isso levaria a um loop sem fim).

É assim que os processos morrem no Android (que também é Linux). A lógica foi aprimorada com a lógica de qual processo remover da existência com base no que o processo está fazendo e na sua idade. Então, os processos do Android simplesmente param de fazer qualquer coisa, mas ficam em segundo plano e o "esgotador de memória" os mata quando precisa de memória para novos.

Jan Hudec
fonte
9

Eu acho que é mais fácil responder isso pela ordem em que a memória é usada.

Pergunta 3: E as seções de texto (código) e dados, como elas são limitadas? Texto e dados são preparados pelo compilador. O requisito para o compilador é garantir que eles estejam acessíveis e empacotá-los na parte inferior do espaço de endereço. O espaço de endereço acessível será limitado pelo hardware, por exemplo, se o registro do ponteiro de instruções for de 32 bits, o espaço de endereço de texto será de 4 GiB.

Pergunta 2: Como o limite é definido? É a memória RAM total disponível? Após o texto e os dados, a área acima disso é a pilha. Com a memória virtual, a pilha pode praticamente crescer até perto do espaço de endereço máximo.

Pergunta 1: a pilha e o heap têm um limite de tamanho estático (por exemplo, 2 gigabytes cada) ou esse limite é dinâmico, mudando de acordo com as alocações de memória durante a execução do programa (ou seja, 4 gigabytes no total a serem usados ​​por ambos, portanto, se um programa usar apenas a pilha, poderá ter uma pilha com 4 gigabytes)? O segmento final no espaço de endereço do processo é a pilha. A pilha leva o segmento final do espaço de endereço e ele começa a partir do final e cresce para baixo .

Como a pilha cresce e a pilha diminui, elas basicamente se limitam. Além disso, como os dois tipos de segmentos são graváveis, nem sempre foi uma violação para um deles ultrapassar o limite, para que você pudesse ter um estouro de buffer ou pilha. Agora existem mecanismos para impedi-los de acontecer.

Há um limite definido para heap (pilha) para cada processo para começar. Esse limite pode ser alterado em tempo de execução (usando brk () / sbrk ()). Basicamente, o que acontece é que, quando o processo precisa de mais espaço de heap e o espaço alocado ficou vazio, a biblioteca padrão emitirá a chamada para o sistema operacional. O sistema operacional alocará uma página, que geralmente será gerenciada pela biblioteca do usuário para o programa usar. Ou seja, se o programa quiser 1 KiB, o sistema operacional fornecerá 4 KiB adicionais e a biblioteca fornecerá 1 KiB ao programa e restarão 3 KiB para uso quando o programa solicitar mais na próxima vez.

Na maioria das vezes, o layout será Texto, Dados, Heap (cresce), espaço não alocado e, finalmente, Empilhar (cresce). Todos eles compartilham o mesmo espaço de endereço.

imel96
fonte