SlideShare une entreprise Scribd logo
1  sur  8
Sistemas Operacionais
                                                                                     Gerenciamento de memória em sistemas Linux
                                                                                                                                Carlos Melo



Memória no Linux: características principais

O Linux é um sistema operacional com memória virtual paginada, isto quer dizer que podemos ter programas em execução cujo tamanho é maior
que a memória física disponível para executá-los. O sistema operacional passa a ser responsável por manter na memória as partes dos programas
efetivamente em uso, deixando o resto no disco rígido. Por exemplo, um programa de 16MB pode ser executado em uma máquina de 4MB de
memória, com o sistema operacional selecionando os 4MB do programa que deverão ser mantidos na memória a cada instante, com as suas partes
sendo copiadas do disco rígido para a memória e vice-versa, quando necessário.


                                             Ou podemos ter, por exemplo, oito programas de 16MB sendo alocados em seções de 4MB de
                                             memória em um computador de 32MB de memória, com o sistema operacional novamente
                                             selecionando os 4MB de cada programa que deverão ser mantidos nas seções de memória a cada
                                             instante, com as suas partes sendo copiadas do disco rígido para a memória e vice-versa, quando
                                             necessário. A utilização da memória virtual torna o computador mais lento, embora faça com que
                                             ele aparente ter mais memória RAM do que realmente tem.


                                             No Linux, a memória funciona com prioridade para processos que estão em execução. Quando um
                                             processo termina, havendo espaço na memória, o sistema mantém resíduos desse processo na
                                             memória para que uma possível volta a processo seja mais rápida. Caso essa memória RAM esteja
                                             lotada com processos que estão em execução, aí se faz uso da memória SWAP (troca).


                                             Cada processo do Linux, em uma máquina de 32 bits, dispõe de 3GB de espaço de endereçamento
                                             virtual para si próprio, com 1GB restante reservado para suas tabelas de páginas e outros dados do
                                             núcleo. O 1GB do núcleo não é visível quando o processo executa no modo usuário, mas torna-se
                                             acessível quando o processo faz uma chamada ao núcleo. O espaço de endereçamento é gerado
                                             quando o processo é criado e sobrescrito em uma chamada ao sistema exec.




Paginação e proteção

O espaço de endereçamento virtual é dividido em áreas ou regiões organizadas em páginas. Contíguas e homogêneas. Isso quer di zer que cada
área consiste de uma série de páginas consecutivas com proteção e propriedades de paginação idênticas. O segmento de código e os arquivos
mapeados são exemplos de áreas. Podem haver vazios no espaço de endereçamento virtual entre essas áreas. Qualquer referência à memória para
um vazio resulta em uma falta de página fatal. O tamanho de página é fixo.


O Linux usa um esquema de paginação de três níveis. Embora tenha sido utilizado no processador Alpha, esse esquema também é empregado de
maneira modificada em todas as arquiteturas. Cada endereço virtual é quebrado em até quatros campos. O campo diretório é usado como índice
do diretório global, sendo que existe um privado para cada processo. O valor encontrado é um ponteiro para um dos diretórios intermediários de
página, o qual é indexado por um campo do endereço virtual. A entrada selecionada aponta para a tabela de página final, a indexada pelo campo
página do endereço virtual. A entrada encontrada aponta para a página requisitada. No Pentium, que usa paginação em dois níveis, cada diretório
intermediário de página tem somente uma entrada, de modo que, efetivamente, a entrada do diretório global é quem escolhe a tabela de página a
usar.


Para a proteção existe um gerenciador de memória virtual evitando que processos no modo Kernel e no modo User se misturem.



Paginação de memória

A memória virtual é usualmente implementada pela divisão da memória em páginas, onde em sistemas Unix são de tipicamente (embora não
necessariamente) de 4kB cada. A tabela de páginas é a estrutura de dados que engloba o mapeamento da memória virtual para endereços físicos.


O tratamento mais simples seria uma longa tabela de página com uma entrada por página (Essas entradas são conhecidas como entradas de
tabela de páginas ou PTE - page table entries). No entanto, esta solução resultaria em uma tabela de página que seria muito grande para ser
encaixada na MMU, dado que tem que ser na memória. A solução, portanto são tabelas de páginas de multiníveis. Desse modo, a medida que o
tamanho dos processos crescem, novas páginas são alocadas e, quando o são, a parte da memória associada à tabela de página é preenchida.


Esse método de gestão de memória que permite que o espaço de armazenamento seja não contíguo. A paginação é suportada por hardware ou por
uma combinação do hardware com o software, dividindo-se a memória física em blocos de tamanho fixo, chamados frames, cujo tamanho é uma
potência de 2. A memória lógica é dividida em blocos do mesmo tamanho, as chamadas páginas.


Um endereço virtual é dividido em 5 campos: diretório de páginas (PGD), diretório superior de páginas (PUD), diretório intermediário de páginas
(PMD), tabela de páginas (PTE) e deslocamento (offset). A arquitetura x86 possui um espaço de endereçamento de 32 bits; quando são utilizadas
páginas de 4 KiB (o padrão) o PUD e o PMD não são utilizados; o PGD e o PTE usam 10 bits cada, e o deslocamento usa 12 bits.
Sistemas Operacionais
                                                                                     Gerenciamento de memória em sistemas Linux
                                                                                                                               Carlos Melo




Outro ponto importante é que a tradução de endereços virtuais para físicos
tem de ser rápida. Isso requer que a tradução seja feita, tanto quanto possível
no hardware. Como não é nada prático colocar a tabela de página por
completo na MMU, a MMU apresenta o que é chamado de TLB: translation
lookaside buffer


Implementação

         A tabela de páginas é guardada na memória principal
         Page-table base register (PTBR) aponta para a tabela de páginas
         Page-table length register (PRLR) indica o tamanho da tabela de
          páginas
         Qualquer acesso a dados/instruções requer 2 acessos à memória:
          um para a tabela de páginas, outro para os dados/instruções
         O problema dos dois acessos à memória pode ser resolvido através
          duma cache de pesquisa rápida, designada por memória associativa
          ou Translation Look-aside Buffers (TLBs)




Memória associativa ou TLB


A MMU (memory managemen unit) da CPU armazena o mapeamento das
tabelas de página mais recentemente usadas. Esse processo é chamado
Translation Lookaside Buffer (TLB). Quando um endereço virtual precisa ser
traduzido em um endereço físico, a busca é feita inicialmente na TLB. Se a
requisição for encontrada, o endereço físico é retornado e o acesso à memória
continua. No entanto, se não foi encontrado, a CPU gera uma page fault e o
sistema operacional terá um interrupt handler para lidar com elas.




Interfaces para o gerenciamento de memória

Existem basicamente quatro momentos em que o sistema operacional trata de paginação. Tais momentos os respectivos tratamentos estão
descritos a seguir:


     1.   Criação do processo
               a.   Determina o tamanho do processo
               b.   Cria a tabela de página
     2.   Quando processo ganha CPU
               a.   Reseta MMU para novo processo
               b.   Limpa TLB
     3.   Interrupção de falta de página
               a.   Identifica qual é o endereço lógico causador da falta
               b.   Escolhe página a ser substituída
               c.   Carrega página requisitada para memória
               d.   Completa a instrução de máquina
     4.   Quando processo termina
               a.   Desaloca tabela de página e páginas na memória e na área de swaping;



Compartilhamento de memória

O compartilhamento de uma região de memória entre dois ou mais processos (executando programas) corresponde a maneira mais rápida deles
efetuarem uma troca de dados. A zona de memória compartilhada (denominada segmento de memória compartilhada) é utilizada por cada um dos
processos como se ela fosse um espaço de endereçamento que pertencesse a cada um dos programas. Em outras palavras, o compart ilhamento de
memória permite aos processos de trabalhar sob um espaço de endereçamento comum em memória virtual. Em consequência, este mecanismo é
dependente da forma de gerenciamento da memória; isto significa que as funcionalidades deste tipo de comunicação interprocessos são fortemente
ligadas ao tipo de arquitetura (máquina) sobre a qual a implementação é realizada.
Sistemas Operacionais
                                                                                     Gerenciamento de memória em sistemas Linux
                                                                                                                                Carlos Melo


Princípio da memória compartilhada

Um processo pode criar um segmento de memória compartilhada e suas estruturas de controle através da função shmget(). Durante essa criação,
os processos devem definir: as permissões de acesso ao segmento de memória compartilhada; o tamanho de bytes do segmento e; a possibilidade
de especificar que a forma de acesso de um processo ao segmento será apenas em modo leitura. Para poder ler e escrever nessa zona de
memória, é necessário estar de posse do identificador (ID) de memória comum, chamado shmid. Este identificador é fornecido pelo sistema
(durante a chamada da função shmget()) para todo processo que fornece a chave associada ao segmento. Após a criação de um segmento de
memória compartilhada, duas operações poderão ser executadas por um processo:


* acoplamento (attachment) ao segmento de memória compartilhada, através da função shmat();


* desacoplamento da memória compartilhada, utilizando a função shmdt().


O acoplamento à memória compartilhada permite ao processo de se associar ao segmento de memória: ele recupera, executando shmat(), um
ponteiro apontando para o início da zona de memória que ele pode utilizar, assim como todos os outros ponteiros para leitura e escrita no
segmento.


O desacoplamento da memória compartilhada permite ao processo de se desassociar de um segmento quando ele não desejar mais utilizá-lo. Após
esta operação, o processo perde a possibilidade de ler ou escrever neste segmento de memória compartilhada.



Mapeamento de arquivos na memória virtual

Um arquivo mapeado na memória é o resultado da associação de o conteúdo de um
arquivo com a porção do espaço de um endereço virtual de um processo. Pode ser
utilizado para compartilhar um arquivo ou memória entre dois ou mais processos.




Mapeamento de arquivo possibilita que uma aplicação se beneficie da memória virtual do
sistema e suplemente o espaço de memória alocado para ele com memória paginável
adicional. Esse mecanismo funciona pela implementação de um mapeamento biunívoco
entre o intervalo de endereços de memória mapeada alocados para a aplicação e o
conteúdo de um arquivo no disco. Uma vez que um intervalo de endereços de arquivos
mapeados foi alocado para uma aplicação, a aplicação pode usar aquele intervalo da
memória de endereços como se ele fosse qualquer outro bloco da memória.


Uma aplicação é livre para usar tantos arquivos mapeados quanto quiser. Da mesma
forma, arquivos mapeados podem ser alocados e desalocados em quando em execução
durante operações particulares de processamento. Por exemplo, digamos que uma
particular função em uma aplicação requereu acesso a uma grande tabela durante a
execução, mas aquela função não era chamada muito frequentemente. Neste caso, a
tabela poderia armazenar num arquivo ao invés de na memória e a função poderia abrir
apenas uma visão de memória mapeada read-only para o arquivo e então acessar
elementos armazenados na tabela no arquivo como se estivesse acessando um elemento num vetor armazenado na memória.


Tratamento de áreas de memória fixas
Partições Fixas

Os sistemas operacionais modernos permitem que mais de um processo seja carregado em memória, de modo que quando um fica bloqueado
esperando por uma operação de E/S outro, que esteja carregado em memória, poderá usar a CPU. Dessa forma, a multiprogramação ajuda a
melhorar a utilização da CPU evitando desperdícios de ciclo de processamento.


Para que seja possível a multiprogramação, podemos dividir a memória em n partições (provavelmente de tamanhos diferentes). Os jobs serão
colocados em filas de entrada associadas à menor partição capaz de armazená-lo. Pelo fato de usarmos partições de tamanho fixo, todo o restante
de espaço de memória não utilizado pelo job será perdido. Este desperdício de memória é chamado de fragmentação interna (espaço de memória
perdido dentro da área alocada ao processo). Por outro lado, imagine que exista duas partições livres, uma de 25 e outra de 100 Kbytes, não
contíguas. Nesse instante é criado um processo de 110 Kbytes que não poderá ser carregado em memória pela forma como ela é gerenciada. Este
problema ocasiona o que chamamos de fragmentação externa (memória perdida fora da área ocupada por um processo). A
figura abaixo ilustra o esquema de organização com partições fixas:
Sistemas Operacionais
                                                                                      Gerenciamento de memória em sistemas Linux
                                                                                                                                  Carlos Melo




O problema da organização em múltiplas filas é que jobs pequenos podem precisar esperar pela liberação de memória (partição mais adequada
para o mesmo), embora exista memória disponível (partição grande), como é o caso da partição 1 e 3. Por outro lado, isso não ocorre no esquema
de uma única fila. Nesta organização (b) sempre que uma nova partição é liberada o job mais próximo do início da fila e que caiba nessa partição
pode ser carregado nela para ser executado pela CPU. No entanto, esta estratégia pode desperdiçar muito espaço ao armazenar u m job pequeno
em uma partição grande. Assim, uma opção mais interessante seria pesquisar em toda a fila de entrada e alocar a partição disponível ao maior job
que pudesse ser carregado. Qual o problema dessa solução? (Discriminar jobs pequenos!) Qual a solução? (Ter pelo menos uma partição
pequena!).


Existe outra possibilidade consiste em estabelecer uma quantidade máxima k de vezes que um job pudesse ser excluído da escolha de receber uma
partição. Assim, sempre que ele fosse preterido teria seu contador incrementado e, ao chegar em k vezes, ele teria que receber uma partição.


Problemas


        Desperdício de memória provocando a fragmentação interna (quando o espaço da partição é maior do que o necessário para executar o
         programa, sobra uma área livre de memória que não pode ser reaproveitada por outro processo).
        Não é possível o uso de 2 partições para um mesmo processo. Isto gera a fragmentação externa quando temos memória disponível mas
         não podemos executar o processo pois não temos uma partição grande o suficiente para executar o processo


Segurança
Realocação e Proteção

Há a necessidade de realocações, pois processos diferentes executam em posições diferentes de memória e com endereços diferentes. Uma
possível solução é modificar as instruções conforme o programa é carregado na memória (quando o SO carrega o programa, adiciona a todas as
instruções que se referenciarem a endereços, o valor do ponto inicial de carga do programa). Esta solução exige que o linker coloque no início do
código do programa, uma tabela que apresente as indicações das posições no programa que devem ser modificadas no carregamento. Mas isso não
resolve a proteção, pois um programa malicioso ou errado pode ler ou alterar posições na memória de outros usuários, já que as referências são
sempre as posições absolutas de memória.


Uma solução adotada para isso foi dividir a memória em unidades de 2 KB e associar um código de proteção de 4 bits a cada uma dessas regiões.
Durante a execução de um processo, o PSW contém um código de 4 bits que é testado com todos os acessos à memória realizados pelo processo,
e gera uma interrupção se tentar acessar uma região de código diferente.


Uma solução alternativa para o problema da realocação e da proteção é a utilização de registradores de base e limite. Sempre que um processo é
carregado na memória, o SO ajusta o valor do registrador de base de acordo com a disponibilidade de memória. Toda vez que um acesso é
realizado na memória pelo processo, o valor do registrado é automaticamente somado, assim não há necessidade de que o código do programa
seja modificado durante o carregamento. O registrador de limite indica o espaço de memória que o processo pode executar, então todo acesso
realizado pelo processo à memória é testado com o valor do registrador limite para a validação do seu acesso. O método dos re gistradores permite
que um programa seja movido na memória, mesmo após já estar em execução, o que antes não era possível sem antes alterar os endereços
novamente.


Área de Swap

Mesmo com o aumento da eficiência da multiprogramação e, particularmente, da gerência de memória, muitas vezes um programa não podia ser
executado por falta de uma partição livre disponível. A técnica de swapping foi introduzida para contornar o problema da insuficiência de memória
principal.
Sistemas Operacionais
                                                                                      Gerenciamento de memória em sistemas Linux
                                                                                                                                 Carlos Melo

O swapping é uma técnica aplicada à gerência de memória para programas que esperam por memória livre para serem executados. Nesta
situação, o sistema escolhe um processo residente, que é transferido da memória principal para a memória secundária (swap out), geralmente
disco. Posteriormente, o processo é carregado de volta da memória secundária para a memória principal (swap in) e pode continuar sua execução
como se nada tivesse ocorrido.


O algoritmo de escolha do processo a ser retirado da memória principal deve
priorizar aquele com menores chances de ser executado, para evitar o swapping
desnecessário de um processo que será executado logo em seguida. Os
processos retirados da memória estão geralmente no estado de espera, mas
existe a possibilidade de um processo no estado de pronto também ser
selecionado. No primeiro caso, o processo é dito no estado de espera
outswapped e no segundo caso no estado de pronto outswapped.


Para que a técnica de swapping seja implementada, é essencial que o sistema
ofereça um loader que implemente a relocação dinâmica de programas. Um
loader relocável que não ofereça esta facilidade permite que um programa seja
colocado em qualquer posição de memória, porém a relocação é apenas
realizada no momento do carregamento. No caso do swapping, um programa
pode sair e voltar diversas vezes para a memória, sendo necessário que a
relocação seja realizada pelo loader a cada carregamento.


A relocação dinâmica é realizada através de um registrador especial denominado
registrador de relocação. No momento em que o programa é carregado na
memória, o registrador recebe o endereço inicial da posição de memória que o
programa irá ocupar. Toda vez que ocorrer uma referência a algum endereço, o
endereço contido na instrução será somado ao conteúdo do registrador, gerando, assim, o endereço físico. Dessa forma, um programa pode ser
carregado em qualquer posição de memória.


O conceito de swapping permite maior compartilhamento da memória principal e, consequentemente, maior utilização dos recursos do sistema
operacional. Seu maior problema é o elevado custo das operações de entrada/saída (swap in/out). Em situações críticas, quando há pouca
memória disponível, o sistema pode ficar quase que dedicado à execução de swapping, deixando de realizar outras tarefas e impedindo a execução
dos processos residentes.


Os primeiros sistemas operacionais que implementaram esta técnica surgiram na década de 1960, como o CTSS do MIT e OS/360 da IBM. Com a
evolução dos sistemas operacionais, novos esquemas de gerência de memória passaram a incorporar a técnica de swapping, como a gerência de
memória virtual.


Problemas

        Grande custo em termos de tempo de execução
        Mais aceitável para sistemas batch ou sistemas com um pequeno número de usuários
        Pode ser usado tanto em partições fixas como variáveis
        No momento do swap-in de memória, é necessário corrigir os endereços de memória do processo.



Testando os limites do sistema

Por padrão, o Linux limita os recursos que cada processo pode ter. Isto é, quanto de recursos do sistema ele pode utilizar. I sso é uma proteção
para que caso o usuário faça algo errado, não prejudique a estabilidade do sistema. Esses limites são:


        RLIMIT_AS: O tamanho máximo que um processo pode ter em bytes.
        RLIMIT_CORE: Quando um processo é abortado, o kernel pode gerar um arquivo core contendo as informações desse aborto. Este valor
         é utilizando para limitar o tamanho desse arquivo. Caso o valor seja zero O, o arquivo não é criado.
        RLIMIT_CPU: O tempo máximo em segundos que um processo pode ser executado.
        RLIMIT_DATA: O tamanho máximo do heap ou memória de dados em bytes.
        RLIMIT_FSIZE: O tamanho máximo em bytes permitido para um arquivo.
        RLIMIT_LOCKS: O número máximo de arquivos que um processo pode dar lock.
        RLIMIT_MEMLOCK: O tamanho máximo em bytes de memória que não permite swap.
        RLIMIT_NOFILE: O número máximo de descritores de arquivos abertos.
        RLIMIT_NPROC: O número máximo de processos que um usuário pode ter.
        RLIMIT_RSS: A quantidade máxima de memória física que um processo pode ter.
        RLIMIT_STACK: O tamanho máximo em bytes da stack.


Neste Blog exploraremos alguns desses limites com a execução de alguns testes, dentre eles: o número máximo de processos criados
(RLIMIT_NPROC), o tamanho máximo de um processo (RLIMIT_AS), a maior área de heap (RLIMIT_DATA), a maior área de pilha (RLIMIT_STACK),
além de uma breve discussão sobre o esgotamento da área de swap.
Sistemas Operacionais
                                                                                      Gerenciamento de memória em sistemas Linux
                                                                                                                                  Carlos Melo

RLIMIT_DATA
carlos@senai:~$ ulimit -d
unlimited
RLIMIT_AS
carlos@senai:~$ ulimit -l
32
RLIMIT_NPROC
carlos@senai:~$ ulimit -u
24499
RLIMIT_STACK
carlos@senai:~$ ulimit -s
8192

Nos próximos itens serão realizados testes buscando explorar tais limites.




Número máximo de processos

Para a checagem no número máximo de processos permitidos, executamos o seguinte código em C:


#include <stdio.h>

main() {
    int i = 0;
    while (fork() != -1) {        // Enquanto não houver falha na criação de processos,
         i++;               // Incrementa i
         printf("n%d",i);       // Imprime o número de fork's encadeados
         sleep(10);            // Delay inserido para possibilitar a impressão na tela
antes do travamento do sistema
    }
    while(1);                   // Permite que o processo continue executanto num loop
infinito.
}

Ao executar o programa observou-se que o último número impresso no console foi 14, significando que o número máximo de processos está entre
214 e 215, confirmando o valor de RLIMIT_NPROC = 24499 obtido pelo comando ulimit -u.


Para obter esse resultado houve dificuldades devido ao travamento do sistema antes de qualquer impressão na tela. O uso do delay sleep(10) foi
crucial para que o valor impresso pudesse ser observado.


Tamanho máximo de processo

O tamanho de um processo está relacionado diretamente com a complexidade das tarefas que ele executa. Não sendo prática a tarefa de aumentar
a complexidade de tais tarefas a fim de testar os limites do tamanho de um processo, aceitaremos o valor RLIMIT_AS fornecido pela função ulimit -
l vista anteriormente. Sendo assim, temos um limite de 32kB para o tamanho de um processo.


carlos@senai:~$ ulimit -l
32

Maior área de heap

A área de heap permite a alocação dinâmica de memória por meio de chamadas, por exemplo, malloc. A área de heap cresce em sentido oposto à
pilha e em direção a esta. Uma maneira de testar sua capacidade é, portanto, alocando memória continuamente, até seu esgotamento, como
mostrado no programa abaixo:


#include<stdio.h>
#include<stdlib.h>
Sistemas Operacionais
                                                                                   Gerenciamento de memória em sistemas Linux
                                                                                                                             Carlos Melo



main(){
    int i = 0, *p;
    while(1){
        i++;
        p = (int*)malloc(sizeof(int));
        printf("n%d Mb alocados até o momento...", sizeof(int)*i/1024/1024);
    }
}


Resultado da execução:

(...)
359 Mb alocados até o momento...
359 Mb alocados até o momento...
359 Mb alocados até o momento...
(...)

Depois de alguns bons minutos de espera, obtivemos as linhas mostradas acima e o programa continuou executando sem nenhum erro. Portanto,
a área de heap é maior que 359MB, valor já bastante elevado quando comparado aos outros limites do sistema e, por isso,
considerada unlimited pela resposta do comando ulimit -d.


Maior área de pilha

Chamamos área de pilha um espaço de memória especialmente reservado para organização de uma pilha de dados, usada como memória auxiliar
durante a execução de uma aplicação. Ao chamarmos um procedimento, passam-se dados e controle de uma parte do código para outra. Nessa
passagem de controle, armazena-se antes endereço de retorno para que o controle possa retornar para este endereço ao final da execução da
função. Este armazenamento é feito na pilha, assim como a passagem de parâmetros dessas funções.


Desse modo, uma forma de testar a capacidade da área de pilha é justamente empilhar sucessivamente vários endereços de retorno, via chamadas
recursivas, atá que sua capacidade seja esgotada. O seguinte programa foi utilizado levando-se em conta esse raciocínio:


#include<stdio.h>
#define T_ADRESS 32
//Variáveis Globais
int nChamadas = 0;
float capacidadeUtilizada = 0;
void fRecursiva();

main(){
    fRecursiva();
}

void fRecursiva(){
    nChamadas++;
    capacidadeUtilizada = capacidadeUtilizada + T_ADRESS;
    printf("n%da chamada:t %f kB da pilha foram                                              utilizados...",             nChamadas,
capacidadeUtilizada/1024);
    fRecursiva();
}


Resultado da execução:

(...)
261734a     chamada:             8179.187500        kB   da   pilha     foram    utilizados...
261735a     chamada:             8179.218750        kB   da   pilha     foram    utilizados...
261736a     chamada:             8179.250000        kB   da   pilha     foram    utilizados...
261737a     chamada:             8179.281250        kB   da   pilha     foram    utilizados...
Sistemas Operacionais
                                                                                   Gerenciamento de memória em sistemas Linux
                                                                                                                               Carlos Melo


Falha de segmentação

O resultado acima nos diz que, considerando um uso de 32bytes da pilha a cada chamada recursiva obtemos a capacidade de pilha de 8MB
esperada com o uso de ulimit -s. Deve-se levar em conta que, antes da execução do programa já havia algo na pilha.


Esgotamento da área de swap

Os kernels 24 e 26 conseguem gerenciar partições de swap de até 2Gb. Assim esse é o limite superior no momento da escolha do tamanho da
partição de swap. Por ser uma área de memória, o SO terá que gerenciar esse espaço constantemente, mesmo que não esteja sendo utilizado,
gerando uma queda de desempenho da máquina em caso de utilização desnecessária de grandes partições de swap. Dado que há um limite
superior de capacidade de gerenciamento pelo sistema operacional e não havendo sentido em ter áreas de swap superiores a essa capacidade, o
conceito de esgotamento é, portanto, não cabível em relação à área de swap.



Referências Bibliográficas
Livros:

         TANENBAUM, Andrew S., Modern Operation Systems.
         Mota Filho, J.E., Descobrindo o Linux.
         RUBEM E. FERREIRA. Linux Guia do Administrador do Sistema, 2a Edição.
         Trabalho retirado parcialmente deste local:   http://ces33.wikidot.com/gerenciamento-de-memoria:jose-gerardo-e-
          diego-alvarez

Sites:

         http://www.vivaolinux.com.br/artigo/Estudo-sobre-os-tipos-de-gerenciamento-do-SO-Linux?pagina=2
         http://www.webartigos.com/articles/2959/1/estudo-sobre-os-gerenciamentos-do-sistema-operacional-linux/pagina1.html
         http://www15.brinkster.com/sharkdj/sistemasoperativos/Detalhe_GM.html
         http://pt-br.kurumin.wikia.com/wiki/Kuruma
         http://ricardobarcelar.com/aulas/so/aula6-mem_virtual.pdf
         http://www.dca.ufrn.br/~adelardo/cursos/DCA409/node96.html
         http://regulus.pcs.usp.br/~jean/so/AULA%2013%20-%20Ger%EAncia%20de%20Mem%F3ria.pdf
         http://www.alexcoletta.eng.br/2008/gerenciamento-de-memoria/
         http://www.scribd.com/doc/5566086/08GERENCIA-DE-MEMORIA
         http://www.marcelotoledo.org/stuff/artigos/processos_no_linux/gerenciamento_de_processos_no_linux.html

Contenu connexe

Tendances

Gerenciamento de Arquivos Nos Sistemas Operacionais
Gerenciamento de Arquivos Nos Sistemas OperacionaisGerenciamento de Arquivos Nos Sistemas Operacionais
Gerenciamento de Arquivos Nos Sistemas OperacionaisLeandro Júnior
 
Sistemas Operativos (Operating Systems)
Sistemas Operativos (Operating Systems)Sistemas Operativos (Operating Systems)
Sistemas Operativos (Operating Systems)Pepe Rocker
 
Sistema Operativo Servidor
Sistema Operativo ServidorSistema Operativo Servidor
Sistema Operativo ServidorDaniel Barros
 
SO de computadores pessoais
SO de computadores pessoaisSO de computadores pessoais
SO de computadores pessoaisAmanda Larentis
 
Manutenção de Computadores - Aula 1
Manutenção de Computadores - Aula 1Manutenção de Computadores - Aula 1
Manutenção de Computadores - Aula 1Guilherme Nonino Rosa
 
Sistemas operacionais
Sistemas operacionaisSistemas operacionais
Sistemas operacionaisvini_campos
 
Seminário Computação em Nuvem
Seminário Computação em NuvemSeminário Computação em Nuvem
Seminário Computação em NuvemLeandro Nunes
 
Aula Introdução a Arquitetura e Organização de Computadores
Aula Introdução a Arquitetura e Organização de ComputadoresAula Introdução a Arquitetura e Organização de Computadores
Aula Introdução a Arquitetura e Organização de ComputadoresGilvan Latreille
 
Sistemas Operacionais - 2 - Tipos de Sistemas Computacionais
Sistemas Operacionais - 2 - Tipos de Sistemas ComputacionaisSistemas Operacionais - 2 - Tipos de Sistemas Computacionais
Sistemas Operacionais - 2 - Tipos de Sistemas ComputacionaisMauro Duarte
 
Unidade 1.4. os dispositivos de entrada e saida mais comuns
Unidade 1.4.   os dispositivos de entrada e saida mais comunsUnidade 1.4.   os dispositivos de entrada e saida mais comuns
Unidade 1.4. os dispositivos de entrada e saida mais comunshenriquecorreiosapo
 
ApresentaçãO2 Sistema Operacional
ApresentaçãO2  Sistema OperacionalApresentaçãO2  Sistema Operacional
ApresentaçãO2 Sistema OperacionalCláudia Costa
 
Gerencia e Administração de Redes
Gerencia e Administração de RedesGerencia e Administração de Redes
Gerencia e Administração de RedesAllan Piter Pressi
 
Introdução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresIntrodução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresMauro Pereira
 

Tendances (20)

Gerenciamento de Arquivos Nos Sistemas Operacionais
Gerenciamento de Arquivos Nos Sistemas OperacionaisGerenciamento de Arquivos Nos Sistemas Operacionais
Gerenciamento de Arquivos Nos Sistemas Operacionais
 
Modelo de von neumann
Modelo de von neumannModelo de von neumann
Modelo de von neumann
 
Sistemas Operativos (Operating Systems)
Sistemas Operativos (Operating Systems)Sistemas Operativos (Operating Systems)
Sistemas Operativos (Operating Systems)
 
Sistema Operativo Servidor
Sistema Operativo ServidorSistema Operativo Servidor
Sistema Operativo Servidor
 
SO de computadores pessoais
SO de computadores pessoaisSO de computadores pessoais
SO de computadores pessoais
 
Microprocessadores
MicroprocessadoresMicroprocessadores
Microprocessadores
 
Manutenção de Computadores - Aula 1
Manutenção de Computadores - Aula 1Manutenção de Computadores - Aula 1
Manutenção de Computadores - Aula 1
 
Sistemas operacionais
Sistemas operacionaisSistemas operacionais
Sistemas operacionais
 
Sistemas operacionais
Sistemas operacionaisSistemas operacionais
Sistemas operacionais
 
Seminário Computação em Nuvem
Seminário Computação em NuvemSeminário Computação em Nuvem
Seminário Computação em Nuvem
 
Aula Introdução a Arquitetura e Organização de Computadores
Aula Introdução a Arquitetura e Organização de ComputadoresAula Introdução a Arquitetura e Organização de Computadores
Aula Introdução a Arquitetura e Organização de Computadores
 
Sistemas Operacionais - 2 - Tipos de Sistemas Computacionais
Sistemas Operacionais - 2 - Tipos de Sistemas ComputacionaisSistemas Operacionais - 2 - Tipos de Sistemas Computacionais
Sistemas Operacionais - 2 - Tipos de Sistemas Computacionais
 
Unidade 1.4. os dispositivos de entrada e saida mais comuns
Unidade 1.4.   os dispositivos de entrada e saida mais comunsUnidade 1.4.   os dispositivos de entrada e saida mais comuns
Unidade 1.4. os dispositivos de entrada e saida mais comuns
 
ApresentaçãO2 Sistema Operacional
ApresentaçãO2  Sistema OperacionalApresentaçãO2  Sistema Operacional
ApresentaçãO2 Sistema Operacional
 
Pacote office
Pacote officePacote office
Pacote office
 
Introdução à Informática - Módulo 1 - O Computador
Introdução à Informática - Módulo 1 - O ComputadorIntrodução à Informática - Módulo 1 - O Computador
Introdução à Informática - Módulo 1 - O Computador
 
Gerencia e Administração de Redes
Gerencia e Administração de RedesGerencia e Administração de Redes
Gerencia e Administração de Redes
 
Sistemas Operativos
Sistemas OperativosSistemas Operativos
Sistemas Operativos
 
Virtualização - Máquinas Virtuais
Virtualização - Máquinas VirtuaisVirtualização - Máquinas Virtuais
Virtualização - Máquinas Virtuais
 
Introdução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresIntrodução à Arquitetura de Computadores
Introdução à Arquitetura de Computadores
 

En vedette

Gerenciamento de Processos no Linux
Gerenciamento de Processos no LinuxGerenciamento de Processos no Linux
Gerenciamento de Processos no LinuxWillian Costa
 
Linux - Inicialização e Gerenciamento de Processos
Linux - Inicialização e Gerenciamento de ProcessosLinux - Inicialização e Gerenciamento de Processos
Linux - Inicialização e Gerenciamento de ProcessosFrederico Madeira
 
Trabalho Linux - Red Hat
Trabalho Linux -  Red HatTrabalho Linux -  Red Hat
Trabalho Linux - Red HatAwsomeInfo
 
Red hat linux
Red hat linuxRed hat linux
Red hat linuxluiiis1
 
RedHat Linux
RedHat LinuxRedHat Linux
RedHat LinuxApo
 

En vedette (9)

Segurança no Linux
Segurança no LinuxSegurança no Linux
Segurança no Linux
 
Gerenciamento de Processos no Linux
Gerenciamento de Processos no LinuxGerenciamento de Processos no Linux
Gerenciamento de Processos no Linux
 
Kernel do Linux
Kernel do LinuxKernel do Linux
Kernel do Linux
 
Qué es red hat
Qué es red hatQué es red hat
Qué es red hat
 
Linux - Inicialização e Gerenciamento de Processos
Linux - Inicialização e Gerenciamento de ProcessosLinux - Inicialização e Gerenciamento de Processos
Linux - Inicialização e Gerenciamento de Processos
 
Trabalho Linux - Red Hat
Trabalho Linux -  Red HatTrabalho Linux -  Red Hat
Trabalho Linux - Red Hat
 
Red hat linux
Red hat linuxRed hat linux
Red hat linux
 
RedHat Linux
RedHat LinuxRedHat Linux
RedHat Linux
 
Red Hat
Red HatRed Hat
Red Hat
 

Similaire à Sistemas operacionais memória no linux

Similaire à Sistemas operacionais memória no linux (20)

Gerenciamento memoria
Gerenciamento memoriaGerenciamento memoria
Gerenciamento memoria
 
Memória Virtual - Aspectos Básicos
Memória Virtual - Aspectos BásicosMemória Virtual - Aspectos Básicos
Memória Virtual - Aspectos Básicos
 
Aula 5a - Sistemas Operacionais
Aula 5a - Sistemas OperacionaisAula 5a - Sistemas Operacionais
Aula 5a - Sistemas Operacionais
 
Aula 3- Disciplina:Pratica Técnico Profi
Aula 3- Disciplina:Pratica Técnico ProfiAula 3- Disciplina:Pratica Técnico Profi
Aula 3- Disciplina:Pratica Técnico Profi
 
Gerencia de memoria
Gerencia de memoriaGerencia de memoria
Gerencia de memoria
 
Gerenciamento de memoria
Gerenciamento de memoriaGerenciamento de memoria
Gerenciamento de memoria
 
S.o aula 3132
S.o aula 3132S.o aula 3132
S.o aula 3132
 
Sistemas Operacionais
Sistemas OperacionaisSistemas Operacionais
Sistemas Operacionais
 
SO03 - Sistemas-Operacionais - Gerencia de Memoria.pdf
SO03 - Sistemas-Operacionais - Gerencia de Memoria.pdfSO03 - Sistemas-Operacionais - Gerencia de Memoria.pdf
SO03 - Sistemas-Operacionais - Gerencia de Memoria.pdf
 
Apostila computacao
Apostila computacaoApostila computacao
Apostila computacao
 
Sistema Operativo 2
Sistema Operativo 2Sistema Operativo 2
Sistema Operativo 2
 
RAM
RAMRAM
RAM
 
Curso openmp
Curso openmpCurso openmp
Curso openmp
 
Gestao de Memoria_SLIDE.pptx
Gestao de Memoria_SLIDE.pptxGestao de Memoria_SLIDE.pptx
Gestao de Memoria_SLIDE.pptx
 
Gerência de Memória
Gerência de MemóriaGerência de Memória
Gerência de Memória
 
355862 slide12-mem virt
355862 slide12-mem virt355862 slide12-mem virt
355862 slide12-mem virt
 
Sistema operacional
Sistema operacionalSistema operacional
Sistema operacional
 
Gerencia de Memória Opensolaris
Gerencia de Memória OpensolarisGerencia de Memória Opensolaris
Gerencia de Memória Opensolaris
 
Trabalho de sd
Trabalho de sdTrabalho de sd
Trabalho de sd
 
Gerência de Memória: Memória Principal
Gerência de Memória: Memória PrincipalGerência de Memória: Memória Principal
Gerência de Memória: Memória Principal
 

Plus de Carlos Melo

Gestão de projetos introduçao
Gestão de projetos introduçaoGestão de projetos introduçao
Gestão de projetos introduçaoCarlos Melo
 
Roteiro da aula prática de sexta à tarde
Roteiro da aula prática de sexta à tardeRoteiro da aula prática de sexta à tarde
Roteiro da aula prática de sexta à tardeCarlos Melo
 
5a.aulacapacitor
5a.aulacapacitor5a.aulacapacitor
5a.aulacapacitorCarlos Melo
 
Atividade final acionamentos
Atividade final   acionamentosAtividade final   acionamentos
Atividade final acionamentosCarlos Melo
 
Questões clp-automação
Questões clp-automaçãoQuestões clp-automação
Questões clp-automaçãoCarlos Melo
 
Apresentação12
Apresentação12Apresentação12
Apresentação12Carlos Melo
 
Gestão da manutenção os 2
Gestão da manutenção os 2Gestão da manutenção os 2
Gestão da manutenção os 2Carlos Melo
 
Gestão da manutenção os 1
Gestão da manutenção os 1Gestão da manutenção os 1
Gestão da manutenção os 1Carlos Melo
 
Desenho técnico cap1
Desenho técnico   cap1Desenho técnico   cap1
Desenho técnico cap1Carlos Melo
 
Eletrônica básica
Eletrônica básicaEletrônica básica
Eletrônica básicaCarlos Melo
 
Analise de circuito indutores
Analise de circuito   indutoresAnalise de circuito   indutores
Analise de circuito indutoresCarlos Melo
 
Notas ete jags - destec
Notas ete   jags - destecNotas ete   jags - destec
Notas ete jags - destecCarlos Melo
 
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12Carlos Melo
 
Recuperação descrição
Recuperação   descriçãoRecuperação   descrição
Recuperação descriçãoCarlos Melo
 
Ete projetos elétricos 2
Ete projetos elétricos 2Ete projetos elétricos 2
Ete projetos elétricos 2Carlos Melo
 

Plus de Carlos Melo (20)

Treinamento 1
Treinamento 1Treinamento 1
Treinamento 1
 
Zener
ZenerZener
Zener
 
Gestão de projetos introduçao
Gestão de projetos introduçaoGestão de projetos introduçao
Gestão de projetos introduçao
 
Capacitancia
CapacitanciaCapacitancia
Capacitancia
 
Roteiro da aula prática de sexta à tarde
Roteiro da aula prática de sexta à tardeRoteiro da aula prática de sexta à tarde
Roteiro da aula prática de sexta à tarde
 
5a.aulacapacitor
5a.aulacapacitor5a.aulacapacitor
5a.aulacapacitor
 
Atividade final acionamentos
Atividade final   acionamentosAtividade final   acionamentos
Atividade final acionamentos
 
Questões clp-automação
Questões clp-automaçãoQuestões clp-automação
Questões clp-automação
 
Apresentação12
Apresentação12Apresentação12
Apresentação12
 
Pneumática
PneumáticaPneumática
Pneumática
 
Gestão da manutenção os 2
Gestão da manutenção os 2Gestão da manutenção os 2
Gestão da manutenção os 2
 
Gestão da manutenção os 1
Gestão da manutenção os 1Gestão da manutenção os 1
Gestão da manutenção os 1
 
Desenho técnico cap1
Desenho técnico   cap1Desenho técnico   cap1
Desenho técnico cap1
 
Eletrônica básica
Eletrônica básicaEletrônica básica
Eletrônica básica
 
Analise de circuito indutores
Analise de circuito   indutoresAnalise de circuito   indutores
Analise de circuito indutores
 
Notas ete jags - destec
Notas ete   jags - destecNotas ete   jags - destec
Notas ete jags - destec
 
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12
Ucr3 fundamentos mecanica_sa1_suporte dosador_1_22_mai12
 
Recuperação descrição
Recuperação   descriçãoRecuperação   descrição
Recuperação descrição
 
Recuperação 1
Recuperação 1Recuperação 1
Recuperação 1
 
Ete projetos elétricos 2
Ete projetos elétricos 2Ete projetos elétricos 2
Ete projetos elétricos 2
 

Sistemas operacionais memória no linux

  • 1. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo Memória no Linux: características principais O Linux é um sistema operacional com memória virtual paginada, isto quer dizer que podemos ter programas em execução cujo tamanho é maior que a memória física disponível para executá-los. O sistema operacional passa a ser responsável por manter na memória as partes dos programas efetivamente em uso, deixando o resto no disco rígido. Por exemplo, um programa de 16MB pode ser executado em uma máquina de 4MB de memória, com o sistema operacional selecionando os 4MB do programa que deverão ser mantidos na memória a cada instante, com as suas partes sendo copiadas do disco rígido para a memória e vice-versa, quando necessário. Ou podemos ter, por exemplo, oito programas de 16MB sendo alocados em seções de 4MB de memória em um computador de 32MB de memória, com o sistema operacional novamente selecionando os 4MB de cada programa que deverão ser mantidos nas seções de memória a cada instante, com as suas partes sendo copiadas do disco rígido para a memória e vice-versa, quando necessário. A utilização da memória virtual torna o computador mais lento, embora faça com que ele aparente ter mais memória RAM do que realmente tem. No Linux, a memória funciona com prioridade para processos que estão em execução. Quando um processo termina, havendo espaço na memória, o sistema mantém resíduos desse processo na memória para que uma possível volta a processo seja mais rápida. Caso essa memória RAM esteja lotada com processos que estão em execução, aí se faz uso da memória SWAP (troca). Cada processo do Linux, em uma máquina de 32 bits, dispõe de 3GB de espaço de endereçamento virtual para si próprio, com 1GB restante reservado para suas tabelas de páginas e outros dados do núcleo. O 1GB do núcleo não é visível quando o processo executa no modo usuário, mas torna-se acessível quando o processo faz uma chamada ao núcleo. O espaço de endereçamento é gerado quando o processo é criado e sobrescrito em uma chamada ao sistema exec. Paginação e proteção O espaço de endereçamento virtual é dividido em áreas ou regiões organizadas em páginas. Contíguas e homogêneas. Isso quer di zer que cada área consiste de uma série de páginas consecutivas com proteção e propriedades de paginação idênticas. O segmento de código e os arquivos mapeados são exemplos de áreas. Podem haver vazios no espaço de endereçamento virtual entre essas áreas. Qualquer referência à memória para um vazio resulta em uma falta de página fatal. O tamanho de página é fixo. O Linux usa um esquema de paginação de três níveis. Embora tenha sido utilizado no processador Alpha, esse esquema também é empregado de maneira modificada em todas as arquiteturas. Cada endereço virtual é quebrado em até quatros campos. O campo diretório é usado como índice do diretório global, sendo que existe um privado para cada processo. O valor encontrado é um ponteiro para um dos diretórios intermediários de página, o qual é indexado por um campo do endereço virtual. A entrada selecionada aponta para a tabela de página final, a indexada pelo campo página do endereço virtual. A entrada encontrada aponta para a página requisitada. No Pentium, que usa paginação em dois níveis, cada diretório intermediário de página tem somente uma entrada, de modo que, efetivamente, a entrada do diretório global é quem escolhe a tabela de página a usar. Para a proteção existe um gerenciador de memória virtual evitando que processos no modo Kernel e no modo User se misturem. Paginação de memória A memória virtual é usualmente implementada pela divisão da memória em páginas, onde em sistemas Unix são de tipicamente (embora não necessariamente) de 4kB cada. A tabela de páginas é a estrutura de dados que engloba o mapeamento da memória virtual para endereços físicos. O tratamento mais simples seria uma longa tabela de página com uma entrada por página (Essas entradas são conhecidas como entradas de tabela de páginas ou PTE - page table entries). No entanto, esta solução resultaria em uma tabela de página que seria muito grande para ser encaixada na MMU, dado que tem que ser na memória. A solução, portanto são tabelas de páginas de multiníveis. Desse modo, a medida que o tamanho dos processos crescem, novas páginas são alocadas e, quando o são, a parte da memória associada à tabela de página é preenchida. Esse método de gestão de memória que permite que o espaço de armazenamento seja não contíguo. A paginação é suportada por hardware ou por uma combinação do hardware com o software, dividindo-se a memória física em blocos de tamanho fixo, chamados frames, cujo tamanho é uma potência de 2. A memória lógica é dividida em blocos do mesmo tamanho, as chamadas páginas. Um endereço virtual é dividido em 5 campos: diretório de páginas (PGD), diretório superior de páginas (PUD), diretório intermediário de páginas (PMD), tabela de páginas (PTE) e deslocamento (offset). A arquitetura x86 possui um espaço de endereçamento de 32 bits; quando são utilizadas páginas de 4 KiB (o padrão) o PUD e o PMD não são utilizados; o PGD e o PTE usam 10 bits cada, e o deslocamento usa 12 bits.
  • 2. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo Outro ponto importante é que a tradução de endereços virtuais para físicos tem de ser rápida. Isso requer que a tradução seja feita, tanto quanto possível no hardware. Como não é nada prático colocar a tabela de página por completo na MMU, a MMU apresenta o que é chamado de TLB: translation lookaside buffer Implementação  A tabela de páginas é guardada na memória principal  Page-table base register (PTBR) aponta para a tabela de páginas  Page-table length register (PRLR) indica o tamanho da tabela de páginas  Qualquer acesso a dados/instruções requer 2 acessos à memória: um para a tabela de páginas, outro para os dados/instruções  O problema dos dois acessos à memória pode ser resolvido através duma cache de pesquisa rápida, designada por memória associativa ou Translation Look-aside Buffers (TLBs) Memória associativa ou TLB A MMU (memory managemen unit) da CPU armazena o mapeamento das tabelas de página mais recentemente usadas. Esse processo é chamado Translation Lookaside Buffer (TLB). Quando um endereço virtual precisa ser traduzido em um endereço físico, a busca é feita inicialmente na TLB. Se a requisição for encontrada, o endereço físico é retornado e o acesso à memória continua. No entanto, se não foi encontrado, a CPU gera uma page fault e o sistema operacional terá um interrupt handler para lidar com elas. Interfaces para o gerenciamento de memória Existem basicamente quatro momentos em que o sistema operacional trata de paginação. Tais momentos os respectivos tratamentos estão descritos a seguir: 1. Criação do processo a. Determina o tamanho do processo b. Cria a tabela de página 2. Quando processo ganha CPU a. Reseta MMU para novo processo b. Limpa TLB 3. Interrupção de falta de página a. Identifica qual é o endereço lógico causador da falta b. Escolhe página a ser substituída c. Carrega página requisitada para memória d. Completa a instrução de máquina 4. Quando processo termina a. Desaloca tabela de página e páginas na memória e na área de swaping; Compartilhamento de memória O compartilhamento de uma região de memória entre dois ou mais processos (executando programas) corresponde a maneira mais rápida deles efetuarem uma troca de dados. A zona de memória compartilhada (denominada segmento de memória compartilhada) é utilizada por cada um dos processos como se ela fosse um espaço de endereçamento que pertencesse a cada um dos programas. Em outras palavras, o compart ilhamento de memória permite aos processos de trabalhar sob um espaço de endereçamento comum em memória virtual. Em consequência, este mecanismo é dependente da forma de gerenciamento da memória; isto significa que as funcionalidades deste tipo de comunicação interprocessos são fortemente ligadas ao tipo de arquitetura (máquina) sobre a qual a implementação é realizada.
  • 3. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo Princípio da memória compartilhada Um processo pode criar um segmento de memória compartilhada e suas estruturas de controle através da função shmget(). Durante essa criação, os processos devem definir: as permissões de acesso ao segmento de memória compartilhada; o tamanho de bytes do segmento e; a possibilidade de especificar que a forma de acesso de um processo ao segmento será apenas em modo leitura. Para poder ler e escrever nessa zona de memória, é necessário estar de posse do identificador (ID) de memória comum, chamado shmid. Este identificador é fornecido pelo sistema (durante a chamada da função shmget()) para todo processo que fornece a chave associada ao segmento. Após a criação de um segmento de memória compartilhada, duas operações poderão ser executadas por um processo: * acoplamento (attachment) ao segmento de memória compartilhada, através da função shmat(); * desacoplamento da memória compartilhada, utilizando a função shmdt(). O acoplamento à memória compartilhada permite ao processo de se associar ao segmento de memória: ele recupera, executando shmat(), um ponteiro apontando para o início da zona de memória que ele pode utilizar, assim como todos os outros ponteiros para leitura e escrita no segmento. O desacoplamento da memória compartilhada permite ao processo de se desassociar de um segmento quando ele não desejar mais utilizá-lo. Após esta operação, o processo perde a possibilidade de ler ou escrever neste segmento de memória compartilhada. Mapeamento de arquivos na memória virtual Um arquivo mapeado na memória é o resultado da associação de o conteúdo de um arquivo com a porção do espaço de um endereço virtual de um processo. Pode ser utilizado para compartilhar um arquivo ou memória entre dois ou mais processos. Mapeamento de arquivo possibilita que uma aplicação se beneficie da memória virtual do sistema e suplemente o espaço de memória alocado para ele com memória paginável adicional. Esse mecanismo funciona pela implementação de um mapeamento biunívoco entre o intervalo de endereços de memória mapeada alocados para a aplicação e o conteúdo de um arquivo no disco. Uma vez que um intervalo de endereços de arquivos mapeados foi alocado para uma aplicação, a aplicação pode usar aquele intervalo da memória de endereços como se ele fosse qualquer outro bloco da memória. Uma aplicação é livre para usar tantos arquivos mapeados quanto quiser. Da mesma forma, arquivos mapeados podem ser alocados e desalocados em quando em execução durante operações particulares de processamento. Por exemplo, digamos que uma particular função em uma aplicação requereu acesso a uma grande tabela durante a execução, mas aquela função não era chamada muito frequentemente. Neste caso, a tabela poderia armazenar num arquivo ao invés de na memória e a função poderia abrir apenas uma visão de memória mapeada read-only para o arquivo e então acessar elementos armazenados na tabela no arquivo como se estivesse acessando um elemento num vetor armazenado na memória. Tratamento de áreas de memória fixas Partições Fixas Os sistemas operacionais modernos permitem que mais de um processo seja carregado em memória, de modo que quando um fica bloqueado esperando por uma operação de E/S outro, que esteja carregado em memória, poderá usar a CPU. Dessa forma, a multiprogramação ajuda a melhorar a utilização da CPU evitando desperdícios de ciclo de processamento. Para que seja possível a multiprogramação, podemos dividir a memória em n partições (provavelmente de tamanhos diferentes). Os jobs serão colocados em filas de entrada associadas à menor partição capaz de armazená-lo. Pelo fato de usarmos partições de tamanho fixo, todo o restante de espaço de memória não utilizado pelo job será perdido. Este desperdício de memória é chamado de fragmentação interna (espaço de memória perdido dentro da área alocada ao processo). Por outro lado, imagine que exista duas partições livres, uma de 25 e outra de 100 Kbytes, não contíguas. Nesse instante é criado um processo de 110 Kbytes que não poderá ser carregado em memória pela forma como ela é gerenciada. Este problema ocasiona o que chamamos de fragmentação externa (memória perdida fora da área ocupada por um processo). A figura abaixo ilustra o esquema de organização com partições fixas:
  • 4. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo O problema da organização em múltiplas filas é que jobs pequenos podem precisar esperar pela liberação de memória (partição mais adequada para o mesmo), embora exista memória disponível (partição grande), como é o caso da partição 1 e 3. Por outro lado, isso não ocorre no esquema de uma única fila. Nesta organização (b) sempre que uma nova partição é liberada o job mais próximo do início da fila e que caiba nessa partição pode ser carregado nela para ser executado pela CPU. No entanto, esta estratégia pode desperdiçar muito espaço ao armazenar u m job pequeno em uma partição grande. Assim, uma opção mais interessante seria pesquisar em toda a fila de entrada e alocar a partição disponível ao maior job que pudesse ser carregado. Qual o problema dessa solução? (Discriminar jobs pequenos!) Qual a solução? (Ter pelo menos uma partição pequena!). Existe outra possibilidade consiste em estabelecer uma quantidade máxima k de vezes que um job pudesse ser excluído da escolha de receber uma partição. Assim, sempre que ele fosse preterido teria seu contador incrementado e, ao chegar em k vezes, ele teria que receber uma partição. Problemas  Desperdício de memória provocando a fragmentação interna (quando o espaço da partição é maior do que o necessário para executar o programa, sobra uma área livre de memória que não pode ser reaproveitada por outro processo).  Não é possível o uso de 2 partições para um mesmo processo. Isto gera a fragmentação externa quando temos memória disponível mas não podemos executar o processo pois não temos uma partição grande o suficiente para executar o processo Segurança Realocação e Proteção Há a necessidade de realocações, pois processos diferentes executam em posições diferentes de memória e com endereços diferentes. Uma possível solução é modificar as instruções conforme o programa é carregado na memória (quando o SO carrega o programa, adiciona a todas as instruções que se referenciarem a endereços, o valor do ponto inicial de carga do programa). Esta solução exige que o linker coloque no início do código do programa, uma tabela que apresente as indicações das posições no programa que devem ser modificadas no carregamento. Mas isso não resolve a proteção, pois um programa malicioso ou errado pode ler ou alterar posições na memória de outros usuários, já que as referências são sempre as posições absolutas de memória. Uma solução adotada para isso foi dividir a memória em unidades de 2 KB e associar um código de proteção de 4 bits a cada uma dessas regiões. Durante a execução de um processo, o PSW contém um código de 4 bits que é testado com todos os acessos à memória realizados pelo processo, e gera uma interrupção se tentar acessar uma região de código diferente. Uma solução alternativa para o problema da realocação e da proteção é a utilização de registradores de base e limite. Sempre que um processo é carregado na memória, o SO ajusta o valor do registrador de base de acordo com a disponibilidade de memória. Toda vez que um acesso é realizado na memória pelo processo, o valor do registrado é automaticamente somado, assim não há necessidade de que o código do programa seja modificado durante o carregamento. O registrador de limite indica o espaço de memória que o processo pode executar, então todo acesso realizado pelo processo à memória é testado com o valor do registrador limite para a validação do seu acesso. O método dos re gistradores permite que um programa seja movido na memória, mesmo após já estar em execução, o que antes não era possível sem antes alterar os endereços novamente. Área de Swap Mesmo com o aumento da eficiência da multiprogramação e, particularmente, da gerência de memória, muitas vezes um programa não podia ser executado por falta de uma partição livre disponível. A técnica de swapping foi introduzida para contornar o problema da insuficiência de memória principal.
  • 5. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo O swapping é uma técnica aplicada à gerência de memória para programas que esperam por memória livre para serem executados. Nesta situação, o sistema escolhe um processo residente, que é transferido da memória principal para a memória secundária (swap out), geralmente disco. Posteriormente, o processo é carregado de volta da memória secundária para a memória principal (swap in) e pode continuar sua execução como se nada tivesse ocorrido. O algoritmo de escolha do processo a ser retirado da memória principal deve priorizar aquele com menores chances de ser executado, para evitar o swapping desnecessário de um processo que será executado logo em seguida. Os processos retirados da memória estão geralmente no estado de espera, mas existe a possibilidade de um processo no estado de pronto também ser selecionado. No primeiro caso, o processo é dito no estado de espera outswapped e no segundo caso no estado de pronto outswapped. Para que a técnica de swapping seja implementada, é essencial que o sistema ofereça um loader que implemente a relocação dinâmica de programas. Um loader relocável que não ofereça esta facilidade permite que um programa seja colocado em qualquer posição de memória, porém a relocação é apenas realizada no momento do carregamento. No caso do swapping, um programa pode sair e voltar diversas vezes para a memória, sendo necessário que a relocação seja realizada pelo loader a cada carregamento. A relocação dinâmica é realizada através de um registrador especial denominado registrador de relocação. No momento em que o programa é carregado na memória, o registrador recebe o endereço inicial da posição de memória que o programa irá ocupar. Toda vez que ocorrer uma referência a algum endereço, o endereço contido na instrução será somado ao conteúdo do registrador, gerando, assim, o endereço físico. Dessa forma, um programa pode ser carregado em qualquer posição de memória. O conceito de swapping permite maior compartilhamento da memória principal e, consequentemente, maior utilização dos recursos do sistema operacional. Seu maior problema é o elevado custo das operações de entrada/saída (swap in/out). Em situações críticas, quando há pouca memória disponível, o sistema pode ficar quase que dedicado à execução de swapping, deixando de realizar outras tarefas e impedindo a execução dos processos residentes. Os primeiros sistemas operacionais que implementaram esta técnica surgiram na década de 1960, como o CTSS do MIT e OS/360 da IBM. Com a evolução dos sistemas operacionais, novos esquemas de gerência de memória passaram a incorporar a técnica de swapping, como a gerência de memória virtual. Problemas  Grande custo em termos de tempo de execução  Mais aceitável para sistemas batch ou sistemas com um pequeno número de usuários  Pode ser usado tanto em partições fixas como variáveis  No momento do swap-in de memória, é necessário corrigir os endereços de memória do processo. Testando os limites do sistema Por padrão, o Linux limita os recursos que cada processo pode ter. Isto é, quanto de recursos do sistema ele pode utilizar. I sso é uma proteção para que caso o usuário faça algo errado, não prejudique a estabilidade do sistema. Esses limites são:  RLIMIT_AS: O tamanho máximo que um processo pode ter em bytes.  RLIMIT_CORE: Quando um processo é abortado, o kernel pode gerar um arquivo core contendo as informações desse aborto. Este valor é utilizando para limitar o tamanho desse arquivo. Caso o valor seja zero O, o arquivo não é criado.  RLIMIT_CPU: O tempo máximo em segundos que um processo pode ser executado.  RLIMIT_DATA: O tamanho máximo do heap ou memória de dados em bytes.  RLIMIT_FSIZE: O tamanho máximo em bytes permitido para um arquivo.  RLIMIT_LOCKS: O número máximo de arquivos que um processo pode dar lock.  RLIMIT_MEMLOCK: O tamanho máximo em bytes de memória que não permite swap.  RLIMIT_NOFILE: O número máximo de descritores de arquivos abertos.  RLIMIT_NPROC: O número máximo de processos que um usuário pode ter.  RLIMIT_RSS: A quantidade máxima de memória física que um processo pode ter.  RLIMIT_STACK: O tamanho máximo em bytes da stack. Neste Blog exploraremos alguns desses limites com a execução de alguns testes, dentre eles: o número máximo de processos criados (RLIMIT_NPROC), o tamanho máximo de um processo (RLIMIT_AS), a maior área de heap (RLIMIT_DATA), a maior área de pilha (RLIMIT_STACK), além de uma breve discussão sobre o esgotamento da área de swap.
  • 6. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo RLIMIT_DATA carlos@senai:~$ ulimit -d unlimited RLIMIT_AS carlos@senai:~$ ulimit -l 32 RLIMIT_NPROC carlos@senai:~$ ulimit -u 24499 RLIMIT_STACK carlos@senai:~$ ulimit -s 8192 Nos próximos itens serão realizados testes buscando explorar tais limites. Número máximo de processos Para a checagem no número máximo de processos permitidos, executamos o seguinte código em C: #include <stdio.h> main() { int i = 0; while (fork() != -1) { // Enquanto não houver falha na criação de processos, i++; // Incrementa i printf("n%d",i); // Imprime o número de fork's encadeados sleep(10); // Delay inserido para possibilitar a impressão na tela antes do travamento do sistema } while(1); // Permite que o processo continue executanto num loop infinito. } Ao executar o programa observou-se que o último número impresso no console foi 14, significando que o número máximo de processos está entre 214 e 215, confirmando o valor de RLIMIT_NPROC = 24499 obtido pelo comando ulimit -u. Para obter esse resultado houve dificuldades devido ao travamento do sistema antes de qualquer impressão na tela. O uso do delay sleep(10) foi crucial para que o valor impresso pudesse ser observado. Tamanho máximo de processo O tamanho de um processo está relacionado diretamente com a complexidade das tarefas que ele executa. Não sendo prática a tarefa de aumentar a complexidade de tais tarefas a fim de testar os limites do tamanho de um processo, aceitaremos o valor RLIMIT_AS fornecido pela função ulimit - l vista anteriormente. Sendo assim, temos um limite de 32kB para o tamanho de um processo. carlos@senai:~$ ulimit -l 32 Maior área de heap A área de heap permite a alocação dinâmica de memória por meio de chamadas, por exemplo, malloc. A área de heap cresce em sentido oposto à pilha e em direção a esta. Uma maneira de testar sua capacidade é, portanto, alocando memória continuamente, até seu esgotamento, como mostrado no programa abaixo: #include<stdio.h> #include<stdlib.h>
  • 7. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo main(){ int i = 0, *p; while(1){ i++; p = (int*)malloc(sizeof(int)); printf("n%d Mb alocados até o momento...", sizeof(int)*i/1024/1024); } } Resultado da execução: (...) 359 Mb alocados até o momento... 359 Mb alocados até o momento... 359 Mb alocados até o momento... (...) Depois de alguns bons minutos de espera, obtivemos as linhas mostradas acima e o programa continuou executando sem nenhum erro. Portanto, a área de heap é maior que 359MB, valor já bastante elevado quando comparado aos outros limites do sistema e, por isso, considerada unlimited pela resposta do comando ulimit -d. Maior área de pilha Chamamos área de pilha um espaço de memória especialmente reservado para organização de uma pilha de dados, usada como memória auxiliar durante a execução de uma aplicação. Ao chamarmos um procedimento, passam-se dados e controle de uma parte do código para outra. Nessa passagem de controle, armazena-se antes endereço de retorno para que o controle possa retornar para este endereço ao final da execução da função. Este armazenamento é feito na pilha, assim como a passagem de parâmetros dessas funções. Desse modo, uma forma de testar a capacidade da área de pilha é justamente empilhar sucessivamente vários endereços de retorno, via chamadas recursivas, atá que sua capacidade seja esgotada. O seguinte programa foi utilizado levando-se em conta esse raciocínio: #include<stdio.h> #define T_ADRESS 32 //Variáveis Globais int nChamadas = 0; float capacidadeUtilizada = 0; void fRecursiva(); main(){ fRecursiva(); } void fRecursiva(){ nChamadas++; capacidadeUtilizada = capacidadeUtilizada + T_ADRESS; printf("n%da chamada:t %f kB da pilha foram utilizados...", nChamadas, capacidadeUtilizada/1024); fRecursiva(); } Resultado da execução: (...) 261734a chamada: 8179.187500 kB da pilha foram utilizados... 261735a chamada: 8179.218750 kB da pilha foram utilizados... 261736a chamada: 8179.250000 kB da pilha foram utilizados... 261737a chamada: 8179.281250 kB da pilha foram utilizados...
  • 8. Sistemas Operacionais Gerenciamento de memória em sistemas Linux Carlos Melo Falha de segmentação O resultado acima nos diz que, considerando um uso de 32bytes da pilha a cada chamada recursiva obtemos a capacidade de pilha de 8MB esperada com o uso de ulimit -s. Deve-se levar em conta que, antes da execução do programa já havia algo na pilha. Esgotamento da área de swap Os kernels 24 e 26 conseguem gerenciar partições de swap de até 2Gb. Assim esse é o limite superior no momento da escolha do tamanho da partição de swap. Por ser uma área de memória, o SO terá que gerenciar esse espaço constantemente, mesmo que não esteja sendo utilizado, gerando uma queda de desempenho da máquina em caso de utilização desnecessária de grandes partições de swap. Dado que há um limite superior de capacidade de gerenciamento pelo sistema operacional e não havendo sentido em ter áreas de swap superiores a essa capacidade, o conceito de esgotamento é, portanto, não cabível em relação à área de swap. Referências Bibliográficas Livros:  TANENBAUM, Andrew S., Modern Operation Systems.  Mota Filho, J.E., Descobrindo o Linux.  RUBEM E. FERREIRA. Linux Guia do Administrador do Sistema, 2a Edição.  Trabalho retirado parcialmente deste local: http://ces33.wikidot.com/gerenciamento-de-memoria:jose-gerardo-e- diego-alvarez Sites:  http://www.vivaolinux.com.br/artigo/Estudo-sobre-os-tipos-de-gerenciamento-do-SO-Linux?pagina=2  http://www.webartigos.com/articles/2959/1/estudo-sobre-os-gerenciamentos-do-sistema-operacional-linux/pagina1.html  http://www15.brinkster.com/sharkdj/sistemasoperativos/Detalhe_GM.html  http://pt-br.kurumin.wikia.com/wiki/Kuruma  http://ricardobarcelar.com/aulas/so/aula6-mem_virtual.pdf  http://www.dca.ufrn.br/~adelardo/cursos/DCA409/node96.html  http://regulus.pcs.usp.br/~jean/so/AULA%2013%20-%20Ger%EAncia%20de%20Mem%F3ria.pdf  http://www.alexcoletta.eng.br/2008/gerenciamento-de-memoria/  http://www.scribd.com/doc/5566086/08GERENCIA-DE-MEMORIA  http://www.marcelotoledo.org/stuff/artigos/processos_no_linux/gerenciamento_de_processos_no_linux.html