GERENCIAMENTO DE MEMÓRIA NO LINUX

Propaganda
GERENCIAMENTO DE MEMÓRIA NO LINUX
1.INTRODUÇÃO
2.MEMÓRIA FÍSICA
3.MEMÓRIA VIRTUAL
3.1.REGIÕES DA MEMÓRIA VIRTUAL
3.2.TEMPO DE VIDA DO ESPAÇO DE ENDEREÇAMENTO VIRTUAL
3.3.TROCA DE PROCESSOS E PAGINAÇÃO
3.3.1.PAGINAÇÃO
3.3.2.MEMÓRIA
3.3.2.1.DIRETÓRIO DE PÁGINA
3.3.2.2.DIRETÓRIO INTERMEDIÁRIO DE PÁGINA
3.3.2.3.TABELA DE PÁGINA
3.3.3.SWAPPING
3.3.3.1.TIPOS E ESTRUTURA DE SWAPPING
3.4. MEMÓRIA VIRTUAL DO NÚCLEO
1.INTRODUÇÃO
O Linux é um sistema multiprocessos e multiusuários. Então devemos ter um
controle rígido sobre a memória para que um processo não sobreponha os recursos
(memória) utilizados pelo outro.
Ele possui dois sistemas de gerenciamento de memória. O primeiro é o sistema de
gerenciamento de memória física. Ele cuida da alocação e liberação de blocos de
memória. O segundo é o sistema de gerenciamento de memória virtual. Este tem o
papel de "enganar" os processos dizendo que há memória suficiente quando não há.
Esta técnica pode melhorar a performance do sistema operacional.
A seguir veremos algumas estratégias usadas pelos dois componentes para aumentar
a performance do processamento.
2.MEMÓRIA FÍSICA
O administrador de memória física principal no Linux é o alocador de páginas. Esse
processo é responsável por alocar e liberar páginas físicas, sendo capaz de alocar
grupos de páginas contíguas. O alocador de páginas usa um algoritmo de alocação
de regiões vizinhas, que combina unidades de alocação adjacentes em uma única
unidade. Cada região de memória que pode ser alocada possui uma região adjacente
correspondente, ou vizinha. Sempre que duas regiões vizinhas são liberadas, elas são
combinadas para formar uma região maior. Essa região maior também tem uma
vizinha, com a qual pode ser combinada para formar uma região livre ainda maior.
Como alternativa, quando não existir uma região de memória disponível pequena
para satisfazer a uma requisição de uma pequena porção de memória, uma região
maior de memória é subdividida em duas vizinhas. O sistema utiliza listas ligadas
para áreas disponíveis de cada tamanho permitido. No Linux, o menor tamanho de
área que pode ser alocada usando esse mecanismo corresponde ao de uma única
página física.
As alocações de memória no núcleo do Linux ocorrem estaticamente, por rotinas de
controle que reservam uma área contígua de memória no momento da carga do
sistema, ou dinamicamente, pelo controlador de páginas. Entretanto, as funções do
núcleo não precisam usar o alocador de páginas para reservar memória. Existem
vários outros subsistemas de gerenciamento de memória especializados, que usam o
controlador de páginas subjacente para gerenciar seu próprio espaço de memória. Os
subsistemas de memória mais importantes são o sistema de memória virtual, o
sistema de alocação de áreas de memória de tamanho variável, kmalloc, e o sistema
de alocação de espaço nas duas memórias cache de dados persistentes do núcleo: a
memória cache de áreas de armazenamento temporário e a memória cache de
páginas.
Muitos componentes do Linux precisam alocar espaço a páginas inteiras, mas
freqüentemente pode ser necessário alocar blocos menores de memória. O núcleo
oferece um subsistema adicional para a alocação de áreas de memória de tamanho
variável, sem tamanho previamente definido, podendo ser de apenas alguns bytes,
em vez de uma página inteira. Esse serviço, fornecido pela rotina kmalloc, análoga á
rotina malloc da linguagem C, aloca blocos a páginas inteiras, sob demanda, mas
subdivide esses blocos em partes menores. O núcleo armazena dados sobre os
blocos em uso pelo sistema kmalloc, em listas que contêm, cada uma, apenas blocos
que foram subdivididos em partes de um tamanho especifico. A alocação de
memória envolve selecionar a lista apropriada e retirar a primeira área disponível
dessa lista, ou alocar espaço a uma página e subdividi-lo.
Tanto o controlador de páginas, quanto o kmalloc, não podem ser interrompidos.
Uma rotina que deseje alocar uma área de memória informa a prioridade da sua
requisição à rotina de alocação. Rotinas de interrupção utilizam uma prioridade
atômica, que garante que a requisição seja satisfeita ou que falhe imediatamente,
caso não exista mais memória disponível. Em contraposição, para uma requisição de
memória de um processo comum de usuário, uma área de memória livre é
procurada, sendo o processo bloqueado até que uma área de memória se torne
disponível. A prioridade de alocação também pode ser usada para especificar a
requisição de memória de acesso direto (DMA). Esse recurso é usado em algumas
arquiteturas, como em PCs, onde certas requisições de DMA não podem ser
realizadas sobre qualquer bloco da memória física.
As regiões de memória solicitadas pelo sistema kmalloc ficam alocadas até que
sejam explicitamente liberadas. O sistema kmalloc não pode transferir essas regiões
de uma posição para outra ou liberá-las em resposta a uma diminuição do espaço
livre em memória.
Os outros três subsistemas principais de memória que realizam um gerenciamento
próprio de blocos de memória física são fortemente relacionados entre si. Esses
sistemas gerenciam o uso da memória cache de áreas de armazenamento temporário,
da memória cache de páginas e da memória virtual. A memória cache de áreas de
armazenamento temporário é a principal memória cache do núcleo para dispositivos
de E/S baseada em blocos; além disso constitui o principal mecanismo por meio do
qual as operações de E/S sobre esses dispositivos são realizadas. A memória cache
de páginas armazena páginas inteiras de dados de arquivos e não é restrita apenas
aos dispositivos que fazem E/S usando blocos. Ela também pode ser usada para
armazenar dados transmitidos por meio da rede e é utilizada tanto pelos sistemas de
arquivos originais do Linux, que usam discos, quanto pelo sistema de arquivos de
rede NES. O sistema de memória virtual gerencia o espaço de endereçamento de
cada processo.
Esses três sistemas de memória interagem entre si. A leitura de uma página de dados
para a memória cache de páginas usa a memória cache de áreas de armazenamento
temporário. As páginas da memória cache de páginas podem também usar o sistema
de memória virtual, caso um processo tenha mapeado o arquivo correspondente no
seu espaço de endereçamento. O núcleo usa um contador de referências a cada
página na memória física para que as páginas compartilhadas por dois ou mais
desses subsistemas possam ser liberadas, quando elas não estiverem mais sendo
usadas em nenhum deles.
3.MEMÓRIA VIRTUAL
O sistema de memória virtual do Linux é responsável pelo uso do espaço de
endereçamento de cada processo. Esse sistema aloca espaço de memória virtual sob
demanda e gerencia a transferência de páginas entre o disco e a memória, quando
necessário. No Linux, o administrador de memória virtual usa duas visões do espaço
de endereçamento de um processo: como um conjunto de regiões separadas e como
um conjunto de páginas.
A primeira dessas visões do espaço de endereçamento é a visão lógica, que descreve
as instruções recebidas pelo sistema de memória virtual relativas á organização do
espaço de endereçamento. Nessa visão, o espaço de endereçamento consiste em
regiões separadas, cada qual consistindo em um espaço contíguo de páginas. Essa
região é descrita, internamente, por uma única estrutura vrn_area_struct, que define
as propriedades dessa região, incluindo os direitos de acesso do processo para
realizar operações de leitura, escrita e execução nessa região, assim como dados
relativos aos arquivos associados á região. As regiões de cada espaço de
endereçamento são organizadas em uma árvore binária balanceada, para possibilitar
uma pesquisa eficiente por uma região correspondente a um endereço virtual.
O núcleo usa uma segunda visão de cada espaço de endereçamento. Essa visão é
armazenada nas tabelas de páginas do processo. As entradas nessa tabela de páginas
determinam a posição atual de cada página da memória virtual, esteja ela em disco
ou na memória física. Essa visão do espaço físico é gerenciada por um conjunto de
rotinas, chamadas por tratadores de interrupções de software do núcleo do sistema,
sempre que um processo usa uma página que não está presente na tabela de páginas.
Cada vrn_area_struct contém um apontador para uma tabela de rotinas que
implementam as operações fundamentais de gerenciamento de páginas. Todas as
requisições de leitura ou escrita de páginas não disponíveis são eventualmente
tratadas por uma rotina apropriada, contida na tabela vrn_area_struct, de forma que
as rotinas centrais de gerenciamento de memória não precisam lidar com detalhes
específicos de cada tipo de região de memória.
3.1 REGIÕES DA MEMÓRIA VIRTUAL
O Linux usa regiões da memória virtual de várias maneiras. Uma região pode ser
caracterizada pela memória persistente para onde as páginas dessa região são
copiadas ou de onde suas páginas são lidas. A maioria das regiões de memória
possui uma cópia reserva em um arquivo ou então não possui cópias reservas. Uma
região que não possui cópias reservas constitui o tipo mais simples de memória
virtual. Essas regiões representam memórias de demanda zero: quando um processo
tenta ler uma página dessa região, ele simplesmente recebe uma página de memória
totalmente preenchida com zeros.
Uma região com cópia em um arquivo funciona como uma visão de uma seção desse
arquivo: sempre que um processo tenta usar uma página dessa região, a tabela de
páginas e preenchida com o endereço de uma página da memória cache do núcleo,
correspondente ao endereço da página requerida do arquivo. A mesma página de
memória física é usada tanto pela memória cache de páginas quanto pelas tabelas de
páginas do processo, de modo que qualquer alteração feita sobre o arquivo, pelo
sistema de arquivos, é imediatamente visível a qualquer processo que tenha essa
página mapeada em seu espaço de endereçamento virtual. Vários processos podem
mapear, em seu espaço de endereçamento, uma mesma região de um determinado
arquivo, resultando na utilização da mesma página de memória física por todos esses
processos.
Uma região de memória virtual é também definida pela forma como são tratadas as
operações de escrita sobre essa região. O mapeamento de uma região no espaço de
endereçamento de um processo pode ser privado ou compartilhado. Se um processo
escreve em uma região privada, o controlador de páginas detecta que é necessária
uma cópia-em-escrita, para manter essas atualizações locais ao processo. Por outro
lado, uma operação de escrita sobre uma região compartilhada resulta na atualização
da cópia dessa região mantida na memória, de modo que essa atualização seja
imediatamente visível a todos os processos que usam essa região.
3.2 TEMPO DE VIDA DO ESPAÇO DE ENDEREÇAMENTO VIRTUAL
Existem exatamente duas situações em que o núcleo do sistema cria um novo espaço
de endereçamento virtual: quando um processo executa um novo programa, por
meio de uma chamada à rotina do sistema exec, ou na criação de um novo processo,
por meio da rotina de sistema fork. O primeiro caso é fácil: quando um novo
programa vai ser executado, o processo recebe um novo espaço de endereçamento
virtual, completamente vazio. É responsabilidade das rotinas do sistema carregar o
programa, preenchendo o espaço de endereçamento com regiões da memória virtual.
No segundo caso, a criação de um novo processo pela rotina fork envolve a criação
de uma cópia completa do espaço de endereçamento virtual do processo existente. O
núcleo do sistema copia os descritores vrn_area_struct do processo pai e cria um
novo conjunto de tabelas de páginas para o processo filho. As tabelas de páginas do
processo pai são diretamente copiadas nas tabelas do processo filho, incrementando
o contador de referências de cada página. Portanto, após uma chamada á rotina fork,
o processo pai e o processo filho compartilham as mesmas páginas físicas de
memória em seus espaços de endereçamento.
Um caso especial ocorre quando essa operação de cópia envolve uma região privada
da memória. Qualquer página que tenha sido escrita pelo processo pai nessa região é
uma página privada, e as alterações subseqüentes dessa página, sejam pelo processo
pai, ou pelo processo filho, não devem ser refletidas na página do espaço de
endereçamento do outro processo. Quando as entradas da tabela de páginas
correspondentes a essas páginas são copiadas, elas são reservadas apenas para leitura
e marcadas como páginas de cópia-em-escrita. Se essas páginas nunca forem
modificadas por qualquer um dos processos, ambos continuam compartilhando a
mesma página de memória física. Entretanto, se qualquer um dos processos tentar
modificar uma página marcada como página de cópia-em-escrita, o contador de
referências dessa página será verificado. Se a página ainda continuar compartilhada,
o processo copiará seu conteúdo para uma nova página de memória física e usará
essa nova cópia. Esse mecanismo assegura que páginas de dados privados sejam
compartilhadas entre processos sempre que possível: serão feitas cópias somente
quando for absolutamente necessário.
3.3 TROCA DE PROCESSOS E PAGINAÇÃO
Uma tarefa importante do sistema de memória virtual é a transferência de páginas,
da memória física para o disco, quando necessário. Os primeiros sistemas UNIX
transferiam todos os dados de um processo de uma única vez. Sistemas UNIX mais
modernos usam o mecanismo de paginação, que transfere páginas da memória
virtual individualmente entre a memória física e o disco. O Linux usa o mecanismo
de paginação, em vez de transferir todos os dados de um processo de uma única vez.
3.3.1 Paginação
Com a ajuda de tabelas, o sistema operacional mapeia um grande espaço de
endereçamento lógico num espaço de endereçamento físico menor. Quando os
processos precisam de mais memória principal do que está fisicamente presente,
segmentos individuais de memória lógica que não foram referenciados recentemente
são realocados no Disco Rígido.
Quando um programa acessa um endereço lógico que está atualmente localizado no
Disco Rígido, o respectivo segmento de memória (chamado página) é carregado na
memória principal, enquanto outro segmento de memória precisa ser escrito para o
Disco Rígido para compensar. Devido ao tempo de acesso do Disco Rígido ser
significativamente mais alto se comparado com a memória principal, há
naturalmente um preço a ser pago em termos de velocidade de execução.
A fim de ser capaz de usar o Disco Rígido para o gerenciamento de memória virtual
e a memória principal lógica, swap files (arquivos de troca) ou swap partitions
(partições de troca) devem ser criados no Disco Rígido. Sem tais partições ou
arquivos, a memória principal é limitada ao seu tamanho físico disponível
realmente.
O sistema de paginação pode ser dividido em duas partes. A primeira consiste no
algoritmo que define a política de substituição de páginas, que escolhe a página que
vai ser copiada da memória para o disco e determina quando essa página deve ser
copiada. A segunda consiste no mecanismo de paginação, que realiza a transferência
dos dados entre a memória e o disco, quando necessário.
A política de substituição de páginas do Linux usa uma versão modificada do
algoritmo do relógio (ou de segunda chance). O Linux usa um relógio de vários
passos e cada página tem uma idade, ajustada a cada passo do relógio. Mais
precisamente, a idade é uma medida da juventude da página, isto é, de quantas vezes
a página foi usada recentemente. As páginas freqüentemente usadas terão idade
maior e a idade de uma página pouco usada vai caindo gradualmente, a cada passo
do relógio, até atingir o valor zero. Essa informação sobre a idade das páginas
permite que o algoritmo de substituição selecione uma página com base na política
MRU.
O mecanismo de paginação oferece suporte ao gerenciamento de páginas, tanto para
dispositivos e partições dedicados à troca de processos, como para arquivos comuns,
embora a troca de páginas de arquivos comuns seja substancialmente mais lenta, em
razão da sobrecarga extra, devida ao sistema de arquivos. Os blocos são alocados a
partir dos dispositivos de troca, de acordo com uma tabela de blocos em uso, que é
armazenada na memória principal. O processo que faz a alocação usa um algoritmo
que escolhe a próxima área de tamanho suficiente para armazenar os dados
requeridos, tentando escrever as páginas em blocos contíguos do disco, para obter
melhor desempenho. Para registrar a informação de que uma página foi escrita de
volta no disco, esse processo usa uma técnica disponível nas tabelas de páginas de
processadores modernos: ele liga o bit de página não presente da entrada
correspondente à página na tabela de páginas, possibilitando que o restante dessa
entrada seja preenchido com o endereço onde a página foi escrita no disco.
3.3.2 Memória
Os níveis do cache são inicializados pela BIOS e portanto, tornam-se transparentes à
programação. Por essa razão, os níveis do cache não são mapeados pelo modelo de
memória de arquitetura independente e o termo memória física em geral é usada
para se referir à RAM. A memória física é dividida em páginas, na qual é definida
no arquivo "asm/page.h" com tamanho de 4 KB para processadores x86 e 8 KB para
processadores Alpha.
A conversão do endereço da memória linear para o endereço da memória física é
feita pelo processador ou pela MMU (Memory Management Unit). Esta conversão é
feita em 3 níveis, na qual o endereço linear é dividido em 4 partes. A primeira parte
é usada como um índice no diretório de página (page directory) e sua entrada faz
referência ao diretório intermediário de página (page middle directory). A segunda
parte é usada como índice do diretório intermediário de páginas, que por sua vez, faz
referência à Tabela de Páginas (page table). A terceira parte é um índice da Tabela
de Página, que aponta (se possível) para uma página na memória física. Finalmente,
a quarta parte do endereço fornece o deslocamento dentro da página de memória
física selecionada.
Os processadores x86 suportam apenas conversões em dois níveis. Neste caso, o
tamanho do diretório de página intermediária (pmd) é definida como um e a entrada
do diretório de página (pgd) passa a ser interpretada como um diretório de página
intermediária (pmd). Entretanto, a conversão do endereço linear deve ser dado em 3
níveis (segundo a definição do modelo de memória de arquitetura independente).
Como consequência, há um aumento da pgd e da tabela de página.
3.3.2.1 Diretório de Página (Page Directory)
As definições de como tipos de dados, funções e macros acessam e modificam
páginas da tabela ou diretório estão nos arquivos "asm/page.h" e "asm/pgtable.h".
As entradas do diretório de página são dados do tipo pgd_t, que é definida como
estrutura e acessado pelo método pgd_val().
Os métodos que devem ser selecionados quando o arquivo "asm/pgtable.h" é
compilado são:
pgd_alloc()
pgd_bad()
pgd_clear()
pgd_free()
pgd_inuse()
pgd_none()
pgd_offset()
pgd_page()
Aloca uma página para o diretório de páginas e preenche-a
com zero
Pode ser usado para testar se a entrada no diretório de página é
válida
Apaga a entrada no diretório de páginas
Libera a página de memória alocada para o diretório de
páginas
Confere se o diretório de páginas está sendo usado por algum
processo
Testa se a entrada foi inicializada
Retorna o ponteiro para a entrada no diretório de páginas de
um endereço linear
O endereço da página a qual a entrada no diretório de página se
refere - usualmente o endereço base de um diretório
intermediário de página. Na arquitetura X86 esta função
retorna o endereço base de uma tabela de páginas se
THREE_LEVEL não é setada
pgd_present()
Mostra se a entrada no diretório de página se refere a um
diretório intermediário de páginas. Na arquitetura X86, se a
macro THREE_LEVEL não estiver definida, esta função testa
se o diretório de páginas se refere a uma tabela de páginas
pgd_reuse()
O contador de uso do diretório de páginas é incrementado em
um
pgd_set()
A entrada no diretório de páginas é setada para o endereço base
de um diretório intermediário de páginas. Na arquitetura X86,
se a macro THREE_LEVEL não estiver definida, esta função é
programada para setar o endereço base de uma tabela de
páginas
SET_PAGE_DIR() Esta macro/função reseta o endereço base do diretório de
páginas para uma tarefa
3.3.2.2 Diretório Intermediário de Página (Page Middle Directory)
As entradas do diretório intermediário de página são dados do tipo pmd_t e o acesso
é feito pelo método pmd_val(). As funções abaixo são definidas:
pmd_alloc()
Aloca um diretório intermediário de página na área do usuário
pmd_alloc_kernel() Aloca um diretório intermediário de página para a memória no
segmento do kernel. Todos os dados são setados para inválidos
pmd_bad()
Testa a validade do diretório intermediária de página
pmd_clear()
Deleta a entrada do diretório intermediário de página
pmd_free()
Libera a entrada da diretório intermediário de página
pmd_free_kernel() Libera um diretório intermediário de página da memória do
segmento de kernel
pmd_inuse()
Testa se o diretório intermediário de página está sendo usado
por um ou mais processos
pmd_none()
Testa se o diretório intermediário de página foi setado
pmd_offset()
Retorna o endereço de uma entrada no diretório intermediário
de página, na qual o endereço no argumento é alocado: a
entrada do diretório correto deve ser passado como parâmetro
pmd_page()
Retorna o endereço base de uma tabela de página para o qual a
entrada se refere
pmd_present()
Testa a presença de uma tabela de página referente a entrada
no diretório intermediário de página
pmd_set()
pmd_reuse()
Seta a entrada no diretório intermediário de página para a base
de endereço de uma tabela de página (não é definido para
arquitetura x86)
Incrementa o contador para os processos usando o diretório
intermediário de página referenciado por parâmetro
3.3.2.3 Tabela de Página (Page Table)
Uma entrada na tabela de páginas é definida pelo tipo de dados pte_t. Como antes,
há uma macro pte_val(), que fornece acesso ao valor do tipo de dados.
Uma entrada na tabela de páginas define um número de atributos para a página de
memória referenciada. Estes começam com um número de atributos de proteção de
memória, permitindo que a página seja lida, escrita e executada. Além disso, existem
os atributos 'copy-on-write', 'dirty' e 'age'. Há outros atributos como estes, mas estes
não podem ser modificados individualmente pela funções fornecidas no modelo de
memória de arquitetura independente. Portanto, as seguintes combinações de
atributos são definidas como macros do tipo pgprot_t :
PAGE_NONE
PAGE_SHARED
PAGE_COPY
PAGE_READONLY
PAGE_KERNEL
Nenhuma página da memória é referenciada pela entrada na
tabela de páginas
Esta página de memória pode ser referenciada por um
número de processos. Todos os tipos de acesso são
permitidos
Esta página de memória pode ser referenciada por um
número de processos. O atributo 'copy-on-write' é setado
É permitido somente acesso de leitura ou execução para
esta página de memória
Acesso a esta página de memória é permitido somente no
segmento do kernel
Uma série de funções foram definidas para manipular as entradas na tabela de
páginas e seus atributos. Note que as funções são descritas aqui pela referência a
atributos explicados acima. Para arquiteturas que não suportam todos os atributos
para páginas definidas no modelo de memória de arquitetura independente, os
significados podem variar.
mk_pte()
Retorna uma entrada na tabela de páginas gerada do endereço
de memória de uma página e uma variável do tipo pgprot_t, que
descreve a proteção de memória para a página
pte_alloc()
Aloca uma nova tabela de páginas
pte_alloc_kernel() Aloca uma nova tabela de páginas para a memória no segmento
do kernel
pte_clear()
Limpa a entrada na tabela de páginas
pte_cow()
pte_dirty()
pte_exec()
pte_exprotect()
pte_free()
pte_free_kernel()
pte_inuse()
pte_mkclean()
pte_mkcow()
pte_mkdirty()
pte_mkexec()
pte_mkold()
pte_mkread()
pte_mkwrite()
pte_mkyoung()
pte_modify()
pte_none()
pte_offset()
pte_page()
pte_present()
pte_rdprotect()
pte_read()
pte_reuse()
Verifica a entrada na tabela de páginas para ver se o atributo
'copy-on-write' está setado
Verifica se o atributo 'dirty' está setado
Verifica se a execução de código na página de memória
referenciada é permitida, isto é, se o atributo 'execute' está
setado
Limpa o atributo 'execute'
Libera a tabela de páginas
Libera a tabela de páginas responsável por gerenciar as páginas
no segmento do kernel
Verifica se a tabela de páginas está sendo referenciada por
quaisquer processos
Limpa o atributo 'dirty'
Seta o atributo 'copy-on-write' para a página de memória
referenciada
Seta o atributo 'dirty'
Seta o atributo 'execute', código de permissão na página a ser
executada
Seta o atributo 'age'
Seta o atributo 'read' para conceder acesso à leitura para a
página
Seta o atributo 'write' para conceder acesso à leitura para a
página
Limpa o atributo 'age'
O atributo de proteção para a página de memória referenciada
pela entrada na tabela de páginas é modificada conforme
definido no parâmetro
Verifica se a entrada na tabela de páginas está setada
Retorna um ponteiro para a entrada na tabela de páginas
referenciando a página de memória à qual o endereço passado
como um parâmetro faz referência. Portanto, o parâmetro
passado deve ser a entrada no diretório intermediário de páginas
válida para esta página
Retorna o endereço da página referenciada pela entrada na
tabela de páginas
Verifica se uma página na memória física é referenciada pela
entrada na tabela de páginas
Limpa o atributo 'read' para proteger a página referenciada pela
entrada na tabela de páginas contra acessos de leitura
Verifica se o atributo 'read' está setado
Incrementa de 1 o contador para o número de processos usando
esta tabela de páginas
pte_uncow()
pte_write()
pte_wrprotect()
pte_young()
Limpa copy-on-write para a página referenciada
Verifica a autorização de escrita para a página referenciada
testando o atributo 'write'
Seta o atributo 'write' para ativar a proteção de escrita para a
página referenciada
Verifica que o atributo 'age' não está setado
3.3.3 Swapping
É uma operação realizada pelo Sistema Operacional quando há a necessidade de um
processo trazer uma página virtual para a memória física e não há páginas físicas
livres disponíveis. Neste caso, o Sistema Operacional prioriza esta página,
descartando outra página de memória física.
Se a página a ser descartada da memória física veio de arquivo de uma imagem ou
de dados e não foi escrita para a página então, ela não precisa ser gravada. Ao invés
disso, pode ser descartada e se o processo precisar daquela página novamente, ela
pode ser trazida de volta do arquivo de imagem ou de dados para a memória.
Portanto, se a página foi modificada, o Sistema Operacional deve preservar o
conteúdo de cada página a fim de que possam ser acessadas posteriormente. Este
tipo de página é conhecida como uma dirty page e quando é removida da memória,
ela é gravada num grupo especial de arquivos chamado swap file (arquivo de troca).
Acessos ao swap file são muito grandes em relação à velocidade do processador e à
memória física e o Sistema Operacional deve atender à necessidade de escrever
páginas para o disco com a necessidade de conservá-las na memória para serem
usadas novamente.
Se o algoritmo decide quais páginas descartar ou trocar (o algoritmo de swap (troca)
não é eficiente) então uma condição conhecida como thrashing ocorre. Neste caso,
as páginas estão constantemente sendo escritas para o disco e estão sendo lidas de
volta e o Sistema Operacional está ocupado demais para permitir que muito trabalho
real seja realizado. Se, por exemplo, o quadro de página física número 1 está sendo
regularmente acessado então ele não é um bom candidato para o swapping para o
Disco Rígido. O conjunto de páginas que um processo está atualmente usando é
chamado de working set (conjunto de trabalho). Um esquema de swap eficiente teria
certeza de que todos os processos têm seu conjunto de trabalho na memória física.
O Linux usa uma técnica chamada página LRU (Least Recently Used - Menos
Usada Recentemente) que permite escolher páginas que podem ser removidas do
sistema. Este esquema envolve cada página no sistema tendo uma idade que muda
quando a página é acessada. Quanto mais a página é acessada, mais nova ela é;
quanto menos ela é acessada, mais antiga e mais passada ela se torna. Páginas
antigas são boas candidatas para o swapping.
3.3.3.1 Tipos e Estrutura de Swapping
O Linux executa o swapping de duas formas. Na primeira, o chamado dispositivo de
swap, usa-se um bloco completo de um dispositivo como arquivo de swap, uma
partição do Disco Rígido. Na segunda, o chamado arquivo de swap, usa-se arquivos
de tamanho fixo. Para facilitar, será usado o termo espaço de swap para referência
dos dispositivos de swap e arquivos de swap.
Existe uma estrutura definida para espaço de swap. Os primeiros 4096 bytes contém
um mapa de bits. Os bits setados indicam que a página de memória está disponível
para paginação. O número do espaço de swap contido nos bits setados corresponde
ao deslocamento de bits a partir do início do espaço. Do byte 4086 em diante é
armazenado uma string de caracteres "SWAP_SPACE" como um identificador. Isso
significa que apenas 4086 x 8 - 1 páginas de memória (130784 KB) podem ser
gerenciados no espaço de swap. O Linux permite, além disso, administrar 8 espaços
de swap em paralelo, conforme especificado em MAX_SWAPFILES; mas este
valor pode ser acrescido para 64.
A vantagem de se usar dispositivos de swap ao invés de arquivos de swap é que a
página é sempre salva em blocos consecutivos. Em arquivos de swap, uma página
pode ser salva em vários blocos não contíguos dependendo de como o sistema de
arquivo fragmentou o arquivo quando ele foi criado. Estes blocos então precisam ser
encontrados por meio do inode do arquivo de swap.
Num dispositivo de swap, o primeiro bloco é dado diretamente pelo deslocamento
para a página de memória a ser gravada ou lida. O restante então segue este primeiro
bloco. Quando um dispositivo de swap é usado, somente um pedido de leitura ou
escrita é feito para cada página, enquanto um arquivo de swap pede um número
dependendo da proporção entre o tamanho de página e o tamanho do bloco. Num
caso típico (quando um tamanho de bloco de 1024 bytes é usado) isto é agrupado em
quatro pedidos separados, para áreas de leitura no meio externo que pode não
necessariamente seguir um após o outro. No Disco Rígido, isto causa movimentos
da cabeça de leitura/escrita, o que afeta a velocidade de acesso.
A chamada de sistema swapon loga num dispositivo de swap ou arquivo para o
kernel.
int sys_swapon(const char * special_file);
3.4 MEMÓRIA VIRTUAL DO NÚCLEO
O Linux reserva, para seu próprio uso, uma região do espaço de endereçamento
virtual de cada processo, de tamanho constante e independente do processador. As
entradas da tabela de páginas correspondentes a essas páginas do núcleo são
marcadas como protegidas, para que essas páginas não sejam visíveis ou
modificáveis, para processos que estejam sendo executados em modo usuário. Essa
área de memória virtual do núcleo contém duas regiões. A primeira região é uma
área estática, que contém as referências da tabela de páginas e é utilizada para
facilitar a tradução de endereços físicos em endereços virtuais, quando o núcleo está
sendo executado. A parte central do núcleo, juntamente com todas as páginas
alocadas pelo alocador de páginas, residem nessa área.
O restante da seção reservada ao núcleo, no espaço de endereçamento virtual de um
processo, não é destinado a nenhum propósito específico. As entradas na tabela de
páginas correspondentes a essa faixa de endereços podem ser modificadas pelo
núcleo, se desejado, de modo a apontar para outras áreas de memória. O núcleo
oferece duas rotinas que possibilitam a um processo usar essa memória virtual. A
rotina vmalloc aloca um número arbitrário de páginas de memória física e associa
essas páginas a uma única região da memória virtual do núcleo, possibilitando a
alocação de uma grande área de memória contígua, mesmo que não exista um
número suficiente de páginas de memória física contíguas para satisfazer a
requisição. A rotina vremap associa uma seqüência de endereços de memória virtual
a uma área de memória usada por um controlador de dispositivo, para ser usada para
E/S mapeada em memória.
Download