Baixe o app para aproveitar ainda mais
Prévia do material em texto
SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 1 20) RESUMO AULA PASSADA – FALTA DE MEMÓRIA 20.1) OVERLAY A primeira solução que falei na aula passada foi o Overlay solução mais antiga e não se usa há bastante tempo. Ela consiste em não carregar todo o código do processo na memória, logo você gasta menos memória com o código desse processo. Pelo fato de todo o código não esta na memória você terá rotinas que não vão estar na memória. Estas sub-rotinas não podem ser executadas na CPU. Elas podem ser usadas, pois o processo pode precisar dessas sub-rotinas. Então como vai fazer? O que tem que ser feito é carregar na memória a parte onde estão as sub- rotinas antes de chamar elas. Depois que carrega pode chamar. Essa solução consiste em ficar trocando parte do código entre a memória e o disco de forma que toda vez que você for chamar uma sub-rotina eu tenho que garantir que aquela parte onde está o código daquelas sub-rotinas esteja na memória. E isto é implementado pelo próprio programador que escreveu o código do processo. O programador tem que se preocupar em carregar do disco para memória o código da parte que contem à rotina que vai chamar naquele momento. É uma solução que precisa muito do programador. O sistema operacional dá pouquíssima ajuda. Ajuda que ele dá é uma ajuda trivial que é a capacidade de ler um pedaço do dado arquivo, no caso, o arquivo executável e colocar na memória. E todo o resto que controla isto é feito pelo programador do processo. É bastante custoso para quem estava programando, mas era o que se fazia porque não tinha suporte ao SO para fazer uma coisa melhor do que essa. 20.2) BIBLIOTECA COMPARTILHADA A segunda solução que vimos não usa o disco. O que ela faz é uma coisa que é difícil ter um organismo genérico para se fazer isto. O que é feito nesta solução é economizar memória de alguma forma. Não gastar memória de forma desnecessária. Como isto é feito de forma geral? Não duplicar na memoria um pedaço do código que se repetiria normalmente. Que pedaço de código seria estes? As bibliotecas. Toda linguagem tem uma ou mais bibliotecas de código que normalmente eram incorporadas no arquivo executável e eram executadas quando você chamava a rotina que utilizava esta biblioteca. Então a consequência disto é que quando você tinha dois processos na memória que foram criados na mesma linguagem que utilizava as mesmas bibliotecas havia duplicação de códigos na memória da biblioteca. Pois, os processos utilizavam a mesma biblioteca. Então a biblioteca compartilhada não é incorporada ao arquivo executável. Ela fica em um arquivo separado e durante a execução do processo o SO verifica quais bibliotecas que aquele arquivo executável utiliza. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 2 Nesse momento carrega as bibliotecas na memoria, mas em um lugar diferente do lugar normal do processo. De forma que outro processo que usa a mesma biblioteca vai compartilhar aquela área e não vai ter um gasto duplicado de memoria com o código das bibliotecas. 20.3) SWAP DE PROCESSOS Nessa solução o SO entra quando a memória acaba é o usuário pedi para executar um processo novo. Então não tem memória para executar esse processo novo. O que o SO faz nesta situação? Ele vai escolher um processo para ser salvo em disco e ao fazer isto o SO vai liberar um pedaço da memória. Nesse pedaço que a memória foi liberada o SO carrega o novo processo. E ai você consegue rodar um processo que não conseguiria porque a memória estava cheia. A grande dificuldade é o fato do processo está em disco faz com que ele não seja executado porque ele está em disco. O processador só consegue executar código que está na memória. Quando for necessário executar esse processo, por exemplo, o usuário clicar na janela desse processo. Isto não poderia ser feito porque o processo está em disco. Qual é a solução para esta questão? A solução para essa questão é o SO neste momento. O usuário clica na janela desse processo que está em disco. Nesse momento o SO traz de volta para a memória este processo. Só que se a memória continua cheia. Então como o SO vai conseguir trazer o processo para a memória? Ele consegue trazer fazendo aquilo que vez antes. Que é escolhendo outro processo para ser salvo em disco. Fazendo isto o SO consegue trazer de volta o processo que foi salvo em disco para a memória. O que ocorre é uma troca entre os processos que estão em disco e os processo que estão em memória. Dai o nome swap de processos que quer dizer troca de processos. Esta solução não depende nada do programador. É transparente para quem está programando o processo. Para esta solução poder funcionar tem uma restrição em relação ao endereço que os processos utilizam. O processo está em um conjunto de endereço na memória ele vai para o disco e quando volta para memória vai para outro conjunto de endereço. No caso do SO utilizar endereço absoluto da memória quer dizer a partir do zero não é possível porque depois que o processo começa a executar. Ele passa a ter variáveis que contem endereços que são variáveis ponteiros que com o endereço a partir do zero elas vão apontar onde o processo estava originalmente. Se o processo volta para memória em outro conjunto de endereços estas variáveis ponteiros vão apontar para o lugar original. Nenhum SO hoje em dia sabe corrigir estes endereços contidos nas variáveis ponteiros. Então dessa forma não é possível fazer a correção e ai você não consegue fazer o swap de processo como todo. Isso quando se usa os endereços absolutos. Mas quando não se usa os endereços absolutos, por exemplo, quando você usa registrador de base. O endereço conta a partir da base do processo. Neste caso o swap de processo pode ser feito. O processo vai ao disco quando ele volta para memória ele volta em outro conjunto de endereços e isto não atrapalha o processo desde que o SO muda a base do processo neste momento. Como todo o endereço que o processo usa é a partir da base. Se o SO muda a base tudo continua funcionando. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 3 O critério que o SO utiliza para escolher um processo é escolher os processos que estão no estado bloqueado já algum tempo porque dessa forma. O processo que está bloqueado há muito tempo tende a ficar bloqueado por muito tempo. O processo fica bloqueado no disco e quando é desbloqueado ele tem que voltar para memória. Qual a diferença entre o overlay e o swap? Overly não traz todo o código que está em disco (arquivo executável) para memória quando o processo começa. No swap de processos a memória fica cheia e o SO grava todo o processo em disco e quem faz isto é o SO. No overlay quem decide o que vai para memória é o programador. 21) SOLUÇÃO PARA FALTA DE MEMÓRIA – SEGMENTAÇÃO SOB DEMANDA A segmentação ocorre na memória e depende do hardware ser capaz de implementar a segmentação. Não são todos os hardwares que permitem isso. A Intel, por exemplo, permite. A segmentação usa a memória, que é fisicamente seqüencial, de outra maneira. Ela divide o endereço em duas partes: Segmento e deslocamento. O endereço deixa de ser uma referencia física, e passa a ser um par coordenado. O deslocamento deve ser menor do que o tamanho do segmento. Se o deslocamento for maior, é gerada uma interrupção de HW, e o processo pode ser abortado. Isso aumenta a proteção, pois evita que um processo mexa numa área que não lhe pertença. Como funciona? Existe no HW uma tabela de segmentos, que define a localização e o tamanho do segmento. Para acessar uma variável global, o HW soma o deslocamento do endereço da variável com o endereço base do segmento para obter o endereço físico da variável. Isso acontece se o deslocamento x for menor que o tamanho do segmento.A interrupção gerada é uma interrupção de deslocamento ilegal. 21.1) Diferenças para Registrador de Base: Mais de uma base, uma para cada segmento A tabela de segmentos é referente ao processo em execução. Ao se mudar o processo ativo, mudam os valores da tabela de segmentos, pois mudam os segmentos e suas respectivas localizações. Os valores das tabelas de segmento ficam contidas no PCB. Os valores de tamanho e posição do calculo de endereço físico são armazenados nos registradores de segmento. Os valores dos registradores de segmento são obtidos a partir da tabela de segmento, que é carregado antes dos registradores de segmento. Para evitar a execução de código numa área de dados, e o vôo do programa, os campos de permissão para execução e alteração são utilizados. Quando o processo tenta executar código em área de dados, ou alterar sua área de código, é gerada uma interrupção, o processo é abortado e é gerada uma mensagem de Segment Fault. O segmento escolhido para ir para disco é colocado como inválido no bit de válido e o so gerencia isto, pois, caso o esse segmento seja solicitado o so identifica que está em disco e carrega-o na memória setando este bit como válido novamente. O nome do hardware que gerencia a memória. Existe um componente do hardware (HW) responsável por controlar a memória – Memory Mangement Unit (MMU) – Unidade de SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 4 Gerenciamento de Memória. Este componente é responsável por implementar boa parte da segmentação. Antigamente este componente de HW era um chip separado que ficava na placa mãe. Hoje em dia, não. Esse componente de HW está contido no chip da CPU. Embora ele não faça parte da CPU. A CPU tem registradores, executa instruções, faz cálculos. Isto é a CPU. O componente que organiza a memória é uma coisa que não faz isso. Ele não faz calculo só controla a memória que é uma coisa importante. Alguns dispositivos que antigamente ficavam em um chip na placa mãe estão sendo acoplados no chip da CPU para ter um único chip na placa mãe. Unidade de processamento específicos para gráficos que se chama GPU – Graphical Processing Unit. O que diferencia a GPU da CPU? É o tipo de instrução que tem. No caso da GPU a instrução que ela tem é especifica para o cálculo vetorial, a soma de vetores. É importante também para o processamento de imagens. No caso da CPU a instrução efetua o cálculo número a número. Existe atualmente um movimento dos fabricantes de incorporar no chip da CPU a GPU. Não existe hoje nenhum caso que o componente de HW que gerencia a memória não esteja dentro do chip da CPU. Para você ter um maquina que tenha Segmentação tem que ter um MMU que implemente segmentação. O que é Segmentação? A ideia básica é você ter aquela divisão que o processo tem áreas é uma coisa conhecida pelo próprio hardware. Não é uma coisa que só o SO tem conhecimento que o processo tem 3, 4, 5 áreas e aloca estas áreas na memória. O próprio HW tem conhecimento destas coisas. O que acontece? Normalmente cada área do processo é igual a um segmento. Por exemplo, os segmentos são numerados: - Código: 0 - Dados (variáveis globais e dinâmicas): 1 - Pilha (variáveis locais): 2 - Biblioteca Compartilhada: 3 Então cada área tem um segmento e um número. Durante a programação da linguagem de máquina esses segmentos são usados pelas instruções de linguagem de máquina. Você usa o endereço que leva estes segmentos em consideração. Então, por exemplo, vou chamar uma subrotina da biblioteca: CALL 3: 1000. Onde 3 representa o Nº do segmento e 1000 o Deslocamento a partir do início do segmento. Normalmente você passa um CALL é um endereço a partir do zero ou a partir do registrador de base. No caso acima, tem dois campos. Um campo é justamente qual é o número do segmento. Este campo é referente à biblioteca que pode ter várias sub-rotinas. Qual é a subrotina que está valendo? Que estou chamando neste momento? Este é o segundo campo que é o Deslocamento a partir do inicio do segmento, por exemplo, 1000. Conforme mostra a Figura 1. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 5 O que estou querendo chamar aqui? Uma subrotina dentro da biblioteca. Onde está esta subrotina dentro da biblioteca? 1000 bytes além do início. No ponto sinalizado na Figura 1 está o código que estou chamando. Então todos os endereços que vou utilizar no meu código que usa segmentação são endereços que tem dois campos. Também chamado de endereço bidimensional (Número do segmento e Deslocamento dentro do segmento). Uma observação importante é que quando o computador gera o código na linguagem de máquina. Não se faz menção ao endereço absoluto do lugar onde está a biblioteca. Não estou usando o endereço absoluto no caso da biblioteca compartilhada apresentada na Figura 1. O que torna possível utilizar algumas coisas a segmentação. Uma vantagem da segmentação é fazer a proteção da memória. O que a segmentação propõe? O hardware propõe que ao invés da memória ser uma coisa contínua que a mesma seja bidimensional. A memória não tem mais de um endereço, a memória terá dois valores que dizem onde a memória está. Terá o número do segmento e o deslocamento onde essa memória está. Nº do segmento Deslocamento dentro do segmento Nº do segmento escolhe qual é a área e deslocamento do segmento diz o que dentro da área vai ser. Na Intel: Ex: mov ds, 1 => qual segmento? mov ax, [2500] => qual deslocamento? Vantagem: Com isso, o hardware conhecerá as áreas, e controlará melhor a memória, impede que o processo mexa em áreas que não são suas, ou seja, impede que não haja invasão de segmentos. 1 2500 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 6 mov BX, [2500] => nesse caso o hardware identifica que o processo não tem acesso. Está fora do segmento, então aborta. Outra vantagem é que não importa para o programa onde está o segmento de memória, pois, o programa sabe que é um endereço bidimensional, a memória é contínua, o programa nem sabe que existe, ele só sabe o nº do segmento e o deslocamento. A segmentação possibilita a expansão da pilha. Quanto ao segmento de pilha o hardware ele é capaz de perceber que o topo está no seu limite inferior. O hardware sabe o tamanho do segmento, o hardware levanta interrupção e o SO trata e testa o tamanho da pilha. A segmentação possibilita o reconhecimento do estouro da pilha. 1) No arquivo executável tem um tamanho fixo para cada área então o SO aloca o espaço. 2) O programador tem a capacidade de escolher o tamanho que ele quer para heap e para pilha (Turbo Pascal) 21.2) Aprofundando dos conhecimentos sobre Segmentação: Segmentação cria uma nova forma de ver a memória como uma coisa bidimensional. Quais os mecanismos de hardware para fazer com que a memória seja vista como bidimensional? Pois a memória física de um computador tem só uma dimensão, começa no endereço 0 da memória e vai até um endereço fffffff. A memória que existe em uma máquina ainda é essa, apesar da segmentação mostrar para o programador, áreas como uma coisa bidimensional. Memória Existe uma coisa que é a que faz a intermediação entre a bidimensionalidade e a memória física, se chama Tabela de Segmentos. Ela Tem no mínimo dois lados, ou seja, duas informações: O início do segmento(memória física) e o tamanho do segmento. Para um programa que tenha quatro segmentos (0, 1, 2 , 3), a tabela vai estar dizendo onde esse segmento começa e qual o tamanho dele. fffff P D C 5000 5000 10000 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 7 Início Tamanho 0 10000 5000 1 20000 2000 2 25000 6000 3 35000 5000O 1º segmento começa em 10000 e acaba com 15000 então tem tamanho 5000. O 2º segmento começa em 20000 e acaba com 22000 então tem tamanho 2000. O 3º segmento começa em 25000 e acaba com 31000 então tem tamanho 6000. O 4º segmento começa em 35000 e acaba com 40000 então tem tamanho 5000. Esta tabela de segmentos é o que o hardware conhece, é lá dentro do chip da CPU que tem a tabela de segmentos e ele usa esses valores para validar se o deslocamento dele está fora do segmento e também fazer acesso de fato à memória. Por exemplo, se quiser acessar a posição 3000 do segmento 2, então essa posição da memória vai ser 25000 + 3000 = 28000, essa posição vai estar entre o endereço 25000 e 31000, segundo figura abaixo: Memória /////// 40000 35000 /////// 31000 25000 /////// 22000 20000 /////// 15000 10000 /////// O hardware soma o deslocamento que você forneceu na função com o índice do segmento, no caso acima 25000 + 3000 = 28000, que é o endereço que vai ser utilizado na memória física. A tabela de segmentos é fixa? Não, depende do tamanho do segmento ela estará refletindo como o SO carregou o segmento na memória. O SO carrega a tabela de segmentos e o hardware utiliza para acessar a memória quando as instruções estão executando. Como o hardware executa exatamente? N° do Seg Define entrada Deslocamento O TAM do segmento é comparado com o deslocamento da instrução Gera Interrupção O SO tratará 3000 É maior que 2000 A tabela de segmentos é para cada processo. Se tiver outro processo com dois segmentos e um dos dois segmentos está ativo em certo instante de execução, quando tiver executando o processo 2 estará sendo usado à tabela abaixo. Se eu fizer mov ds, 2 ,não consegue acessar, pois não há segmentos, no processo 2 então será gerado interrupção. Se usar deslocamento 6000 no 3000 mov ax, [3000] 25000 +3000 28000 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 8 segmento 0, vai abortar também. O processo só consegue mexer nos próprios segmentos. Isso evita que um bug no programa faça com que outro processo pare de executar. Início Tam 0 5000 5060 1 15000 3000 Para compartilhar teria que ser feito com que dois processos apontem para o mesmo endereço inicial. O SO vê quantas áreas são e qual tamanho de cada área, então procura espaço na memória para cada segmento, pode ser junto ou separado. O benefício final é que um processo não veja a área de outro processo, não consiga alterar outro. Infelizmente a Microsoft quando criou o Windows 3.1 ela não fez assim, ela não dá uma tabela de segmento por processo, ela cria uma tabela de segmentos para todos os processos, isso é muito ruim, pois permite que um processo entre em um segmento de memória do outro, utiliza segmentação, mas não protege a memória. Além dos campos acima poderemos ter campos de proteção como permissão, alteração, leitura e executável. Vai dizer se aquele segmento permite alteração no dado. Por exemplo, em um segmento de código, não é alterável o conteúdo, mas poderá ser executado. Se o programador tentasse executar uma instrução de alteração em um segmento que não permite alteração também gera interrupção, então o processo é abortado. No caso da Intel que tem segmentação, quando altero o segmento que vamos utilizar, a CPU da Intel não só carrega o valor 2 de ds como carrega todos os dados de controle do segmento 2, isso faz com que não seja necessário ter a tabela de segmentos contida dentro da CPU, não precisará consultar memória, isso é otimização. Outra solução é carregar a tabela de segmentos na CPU, mas a tabela pode ser grande, tornando-se inviável. A tabela de segmentos é definida pelo SO, mas o programador define o tamanho do segmento, ás vezes é o compilador. O SO pode deslocar o segmento de lugar se fizer isso e alterar a tabela de segmentos, o processo não irá perceber que o segmento mudou de lugar. O segmento de pilha tem o tamanho, tem um início e um início real, quando é feito um push, esse push pode alcançar o início real, então ocorre interrupção que o SO trata, baixando um pouco do início real. Se for área de dados, vai abortar. Nos dois casos acontece interrupção, o que muda é o tratamento. O Windows permite a criação de outra área de dados. A tabela de segmentos fica onde? Os dados que ela contém apontam para PCB, a cada instrução que o PCB muda de endereço a CPU tem que validar se o acesso é válido, e além disso tem que somar o início do segmento ao deslocamento, isso é feito a cada instrução que executa, isso é feito de forma rápida, mas para ser rápido, a tabela de segmentos tem que estar dentro do chip da CPU. O problema de fazer isso é que a tabela pode ser grande. A Intel coloca na memória, só que ficando na memória ficaria muito lento para fazer as validações e os cálculos a cada instrução que é executada pela CPU, então a Intel quando o programador indica que quer usar um certo segmento a CPU carrega o registrador dela (a parte escondida do registrador de segmento, o início, o tamanho) ficam contidos dentro da CPU ,então a validação é feita sem precisar ir a memória, portanto a execução de uma instrução vai ser rápida. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 9 21.3) PROPÕE QUE O HARDWARE CONSIDERE A MEMÓRIA COMO SENDO BIDIMENSIONAL. O hardware verifica se há um acesso fora do segmento. Segm. Área da memória Tamanho do segmento 2 5000 1 1000 0 2000 21.4) TABELA DE SEGMENTOS A tabela de segmentos é usada para evitar que um processo não invada a área de código/dados de outro processo. Essa tabela está contida no chip da CPU e tem no mínimo 2 informações: a posição inicial do segmento e o tamanho do segmento. Segm. Início do Segmento Tamanho do segmento 0 20000 2000 1 25000 6000 2 35000 5000 No. do Segmento (áreas) Deslocamento no Segmento 1 2500 MOV AX, [2500] MOV BX, [7000] A última instrução significa que a CPU vai tentar acessar a posição 7000 do segmento 1 mas o segmento tem tamanho menor que 5000. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 10 MOV DS, 2 MOV AX, [3000] A 1a instrução indica que o segmento a ser utilizado é o 2 (DS – segmento de dados) e que deve-se mover o conteúdo do endereço X da memória para o registrador AX. Mas qual o endereço correto que deverá ser acessado? Para isso deve-se consultar a tabela de segmentos que diz que o segmento 2 começa no endereço 35000. Deve-se verificar se o deslocamento indicado na instrução é válido, isto é, nesse exemplo, precisa-se verificar se 3000 é menor que o tamanho do segmento 2 que é de 5000. Nesse caso, o deslocamento é válido e a instrução poderá ser executada normalmente. Caso contrário, haveria uma interrupção e o processo seria abortado. SO Área livre Segmento 2 Área livre Segmento 1 Área livre Área livre Segmento 0 50000 45000 40000 35000 31000 25000 22000 20000 0 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 11 O SO carrega os valores na tabela de segmentos e cada processo tem sua própria tabela. A tabela possui mais dois bits. O bit que diz se determinado segmento pode ser alterado e outro bit que diz se o mesmo segmento pode ser executado. No. Segmento Tam. Segmento Alterável Executável 0 5000 0 1 1 2000 1 0 2 6000 1 0 3 5000 1 0 Se o segmento for de código, o bit Alterável tem que estar setado em 0 e o Executável em 1. E o contrário para os demais segmentos. O segmento de código não pode ser mudado em hipótese alguma durante a permanência na memória. A tabela de segmentos ficano chip da CPU mas a tabela pode acabar sendo grande demais. Por isso a Intel coloca as tabelas de segmento na memória principal mas ficaria muito lento fazer essa validação. Para resolver isso, os dados referentes ao segmento que está sendo usado (número do segmento, tamanho do segmento e os bits Alterável e Executável) são colocados em um registrador da CPU. 22) PROTEÇÃO DA MEMÓRIA Impedir que um processo utilize uma área da memória que não foi alocada a ele. Então um processo não consegue alterar a área de memória de outro processo. A Figura 2 mostra dois processos na memória. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 12 A primeira coisa que a proteção da memória vai me garantir que o processo 2 só vai usar as áreas dele. E o processo 1 só consegue usar as áreas dele. Quem implementa a proteção de memória é o HW e só ele pode proibir que um processo não acesse o endereço que não pertence a ele. Qual é a vantagem da proteção da memória? A vantagem é que um processo com defeito não atinge a memória de outro processo. É muito ruim um processo alterar a memória de outro processo. Por exemplo, o processo 1 se tivesse com defeito tinha que mudar de endereço e poderia alterar a variável do processo 2. O processo 2 não vai funcionar direito, pois o valor da variável foi alterado. Se isto fosse possível o próprio sistema operacional poderia ter suas variáveis alteradas e isto seria muito ruim. Não existir proteção da memória muitas coisas erradas podem acontecer. Quando um processo está com defeito ele pode estragar a própria memória dele, pois ele não consegue alterar as áreas que não são dele. Se ele tentar usar uma área que não é alocada a ele o HW a MMU não vai deixar. Então é a segmentação que introduz este conceito que é muito importante. Então o processo 1 não consegue acessar as áreas de memória do processo 2. Logo, ele não consegue estragar a área do processo 2 e ambos não conseguem estragar a área do Sistema Operacional isto em termos de memória. As vantagens da segmentação são você não ter endereços absolutos sendo usado e a proteção da memória. 23) IMPLEMENTAÇÃO DA SEGMENTAÇÃO Existe uma Tabela para cada processo que guarda os dados dos segmentos do processo. Essa tabela tem um conjunto de registros e tem um registro para cada área do processo. Conforme mostra a Figura 3. Esta tabela é preenchida pelo sistema operacional e ela guarda informação sobre cada segmento do processo. Figura 3 Que informações são estas? Vamos ver duas por enquanto. Início do segmento na memória e o Tamanho do segmento. O processo 2 tem uma tabela equivalente à tabela da Figura 3. Esta tabela é preenchida pelo sistema operacional. De onde vêm as informações que são preenchidas na tabela pelo SO? O tamanho do segmento é um dado de controle que existe no arquivo executável por consequência no processo ou é um dado da biblioteca compartilhada. Com esta informação o SO sabe qual o tamanho de cada segmento. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 13 Como o SO preenche o início do segmento na tabela de segmentos? Usando o algoritmo de alocação. O SO vai rodar um dos algoritmos de alocação n vezes. Uma vez para cada área. E vai alocar uma área de memória para o processo. Então esta área que o SO escolheu e preenchida na coluna início de segmento na tabela de segmentos do processo. Esta tabela vai ser consultada pelo HW na hora da execução do código desse processo. Por exemplo, executar a instrução CALL 3:1000. Onde 3 é o nº do segmento e 1000 é o deslocamento do segmento. Várias coisas acontecem na hora de executar a instrução CALL 3:1000. A primeira coisa que é feita é verificar se o segmento é um segmento válido porque pode não ser. MMU verifica se o segmento é válido. O maior segmento é visto na tabela de segmentos. Neste caso é 3. Verifica se 3 nº segmento informando no CALL é maior que o máximo nº de segmento da tabela. Se for maior tem um problema. Por exemplo, se fosse CALL 5:1000. 5 > 3 . 3 é o máximo segmento da tabela de segmento. Não existe o segmento 5 no processo. Neste caso, a MMU (HW) gera uma interrupção. O que é uma interrupção? É quando a CPU para de fazer o que está fazendo e executa uma outra rotina que é tratadora daquele tipo de interrupção. Por exemplo, neste caso aqui CALL 5:1000. O que o HW vai fazer? Vai vê que 5 > 3 vai gerar uma interrupção. Qualquer rotina que trata interrupção é uma rotina do Sistema Operacional. Então, neste caso especifico, a rotina do SO que trata este tipo de interrupção tipicamente aborta o processo. Esta é a primeira coisa que o HW implementa para garantir a proteção de memória. Supondo que não gerou a interrupção. O número de segmento é usado para identificar qual o registro de segmento que será utilizado para continuar executando esta instrução. É feita uma segunda verificação. Se o valor 1000 (da instrução CALL 3:1000 ) é maior ou menor que Tamanho do Segmento equivalente ao Maximo Número de Segmento da Tabela de Segmentos do Processo 1 = 1000 > 5000? Não. Ok! Mas poderia ser, por exemplo, ao invés de 1000 ser 21000. Se isso fosse possível, estará dentro do processo do Sistema Operacional. 21000>5000? Sim. Isto é um problema e a MMU gera uma interrupção. Tipicamente a rotina do SO que trata este tipo de interrupção aborta o processo. 1000 é somado com o valor do início do segmento, ou seja, 1000 + 45000 = 46000 é o endereço de memória utilizada conforme mostra a Figura 2. O endereço 46000 guarda o código da subrotina a ser executada pela CPU depois que o CALL 3:1000 é feito. Então é um HW mais sofisticado do que o registrador de base e é uma coisa simples. As primeiras CPUs da Intel não tinham isto. Na 3ª geração de CPU de 16 bits da Intel que passou a ter segmentação. Hoje em dia isto é trivial. Outra vantagem é que na segmentação podemos fazer a compactação. Digamos que não tivesse o processo 2 na memória. Conforme mostra a Figura 4. Agora cada segmento tem um novo início. Conforme mostra a Figura 5. Então compactei a memória e alterei o inicio do segmento. A instrução CALL 3:1000 vai continuar executando. Aquela subrotina que estava no 46000 agora está no 21000. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 14 A tabela de segmentos do processo fica no PCB do processo. Cada processo tem a sua tabela e o HW MMU sabe qual é a tabela do processo que está em execução. Então a segmentação faz com que o HW tenha um grande controle do que está na memória. Impedindo que um processo atinja as áreas do outro processo. Esse controle que a MMU HW faz vai além da memória simples. Ela também controla se o processo faz o uso correto de cada uma das suas áreas. Cada área que o processo tem um proposito específico. Figura 4 Figura 5 Área de código contem o código executável do processo que tem que ser executado. Área de dados contem as variáveis globais e as variáveis dinâmicas do processo. Área de pilha contem as variáveis locais do processo que vão ser utilizadas durante a execução dele. Área da biblioteca que contem código executável que é comum a mais de um processo. A tabela de segmentos do processo contém mais dois campos que permitem o HW controlar se o uso das áreas de segmentos está correto. Estes dois campos são chamados de Executável e Alterável. Onde 1 representa que o segmento é executável ou alterável e 0 que o segmento não é executável ou alterável. Conforme mostra a Figura 6. Então este é o controle que o SO preenche na tabela de segmentos do processo. Não faz sentido alterar o código do processo quando ele está executando, geralmente isto é feito alterando o código do arquivo fonte e recompilando. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SAAmancio Página 15 Figura 6 O HW durante a execução de acordo com o tipo de instrução ele permite ou não que o segmento seja alterado ou executado. Por exemplo, CALL 1:500. Isso faz sentido? Não, pois o segmento 1 é não executável. O que vai acontecer? A MMU vai gerar uma interrupção, pois o segmento está definido como não executável na tabela de segmento deste processo. A MMU sempre que vê alguma coisa errada ela gera uma interrupção. E o SO trata a interrupção. Tipicamente o SO aborta o processo com este tipo de interrupção. Porque é um erro um processo ter chamar um subrotina em uma área que contem variável que é a área de dados. Como o HW acessa esta tabela? Existe um registrador que tem o endereço da tabela de segmentos do processo que está em execução. Por exemplo, endereço X que aponta para onde está a tabela. O HW antes de executar vai neste registrador e descobre onde está a tabela de segmentos do processo. Digamos que se tem uma variável local P que é um ponteiro que aponta para variável dinâmica que está na Heap na área de dados. Como é este ponteiro? 1:200. Então a variável dinâmica está no endereço 30200 na área de dados do processo1. Conforme mostra a Figura 7. Figura 7 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 16 Quando se vai usar o ponteiro que fica em outro canto a mesma lógica de verificação se é valido ou não vai acontecer. 24) LINGUAGENS 1 – Compiladas 2 – Compiladas + Interpretada 3 – Interpretadas No caso 1 linguagem compilada, por exemplo, C e Delphi. O compilador compila o código fonte e gera um arquivo executável na linguagem da maquina que vai rodar o arquivo executável. No caso 2 a linguagem precisa primeiro ser compilada par uma linguagem intermediária. A linguagem interpretada às vezes é chamada de máquina virtual no caso do Java. As linguagens do caso 3 não são muito utilizadas. Exemplos, deste tipo de linguagem: arquivo Bat, cmd.exe. Existe um programa que é o interpretador que lê o arquivo fonte e executa este arquivo. Então a CPU ela executa o código executável do interpretador e é o interpretador que lê o que está no arquivo fonte e executa. Evidentemente que um código interpretado é mais lento porque é o código do interpretador que tem que entender o que o programador escreveu. O interpretador tem que entender durante a execução do código fonte. Na linguagem compilada já está direto o que tem que fazer é um CALL. É muito mais rápido, pois está na linguagem de máquina. Todas as verificações são feitas antes do código fonte ser compilado. Então o código gerado é um código perfeito para executar. Na interpretação todas as validações são vista na hora que o arquivo fonte está sendo interpretado. Em Java se compila para um linguagem intermediaria que depois será interpretada para uma linguagem de máquina. A linguagem intermediária é algo mais próximo da linguagem de máquina. O que acontece é que boa parte do trabalho já é feito na compilação que é a validação do código fonte. Add Eax, Ebx isto é o que gera a compilação. O HW executa direto. É mais rápido. No caso do Java a linguagem intermediaria se chama Bytecode. Para agilizar na execução do código Java um mecanismo é utilizado. Este mecanismo se chama Compilação Just in Time. O que é isto? Java tem métodos. Alguém chama um método que está compilado em Bytecode. O compilador interpreta qual método vai executar. Mais tarde este mesmo método é chamado de novo. Então interpretar de novo este método. O método é chamado pela terceira vez. E o Bytecode percebe que estão chamando muito este método. Então ao invés de interpretar de novo. Este método de Bytecode é compilado para linguagem de maquina Intel. Agora quando este método for chamado novamente não será mais executado em Bytecode, mas sim em linguagem de maquina final da Intel. Então com este mecanismo Java não fica muito lento. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 17 A máquina virtual Java é um processo que tem um código, dado, pilha. No interpretador normal o código que ele esta interpretando fica na área de dados dele. Na área de código do interpretador tem um código que interpreta a linguagem intermediaria. Java tem uma coisa diferente que é uma área de código do tipo novo. Uma nova área na memoria do processo da maquina virtual que é uma área. Que onde está gerando o código executável gera o código final e ao mesmo tempo eu preciso de uma área que possa alterar o conteúdo e possa chamar o executável. Então nesse caso a área de compilação que é uma área da maquina virtual do Java. É uma área que vai ter na memoria no bit de executável igual a 1 e no bit de alterável também igual a 1. Então essa e a exceção a regra que quando um é executável não pode ser alterável e quando é alterável não pode ser executável. O que o SO faz quando dá uma interrupção de uso de memória errada? Ele tipicamente aborta o processo, mais isso pode ser alterado pelo programador que criou o processo. Existe uma chamada que permite você alterar o comportamento da rotina do SO que executa o tratamento deste tipo de interrupção. Isto dá uma chance do processo fazer alguma coisa útil antes de abortar. Um exemplo onde isso ocorre e no Office da Microsoft que muda o comportamento normal do SO quando o programa comete uma falha que infringe a proteção da memória. Por exemplo, ocorre um problema no seu documento word. Ao invés do SO abortar o processo que executa o word pedi para executar uma rotina de tratamento do word que salva o que foi feito e recarrega o processo para memória. Mas nem sempre isto é possível, mas quando é possível é muito benéfico. Falha de Segmento (Segmentation Fault) o tipo de interrupção de acesso errado a memória tem esse nome. 25) CONCLUSÃO Nesse mecanismo temos uma visão bidimensional da memória onde a unidade de memória é chamada de segmento. Temos um mapeamento da memória na tabela de segmento que fica carregada na memória e ao executar uma instrução que altera o segmento o sistema operacional vai até a memória pega o segmento referente ao que se deseja executar e carrega o registrador de segmentação na CPU com o segmento desejado. Esta ida a memória só acontece quando o segmento é alterado. Exige um suporte de Hardware e Software. Não existe a necessidade de ter uma TLB no hardware já que se tem o registrador de segmentos que contém o segmento das instruções executadas. PROBLEMAS DA SEGMENTAÇÃO: Fragmentação Externa. Solução evitar a fragmentação utilizando os seguintes algoritmos: Best Fit: aloca o processo na parte da memória cujo tamanho se aproxima do tamanho do processo. First Fit ou Next Fit: aloca o processo na primeira área disponível encontrada a partir da posição anterior. Worst Fit: aloca o processo no maior espaço disponível na memória assim sobrará espaço para outro processo. 26) MEMÓRIA VIRTUAL Não há mais problemas de fragmentação. Os processos tem que ser contínuos no mundo virtual. É possível aumentar a pagina na memória virtual, basta existir paginas reais na memória real. O programa vê como única o espaço de endereçamento virtual. Paginas com tamanho fixo – CPU Intel – 4kb. As áreas de memória virtual que não estão sendo usadas, não precisam ter uma pagina real associada. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 18 Como é feito o mapeamento do mundo virtual para o real? Através da tabela de paginas, uma para cada processo. O HW conhece, utilizado a cada acesso de memória. O numero de paginas no mundo virtual é igual as entradas na tabela de paginas. Possui um bit de presença na tabela de paginas, para identificar qual página está na memória real. Cada processo tem uma tabela de paginas, quando o processo esta rodando. O HW usa esta tabela para fazer o mapeamento. O SO faz parteda memória virtual para que quando o processo fizer uma chamada ao SO, a tabela de paginas ativa não seja trocada na memória. Quando um processo chama uma subrotina referente a uma pagina virtual que não está presente (mapeada p pagina real). O HW gera uma interrupção, podendo abortar o processo. Problemas: 2 acessos a memória real Tabela de paginas muito grande Soluções: Problema relacionado à tradução de Endereços: Memória Associativa Tabela mantida pelo HW, para 1 processo apenas, poucas entradas, memória interna a CPU. Possui bit de validade (bit 1). Primeiro o HW verifica na tabela associativa da CPU, cão não encontre a entrada que deseja, o HW vai a tabela de paginas, encontra a informação que precisa e coloca a mesma na memória associativa, para não acessar novamente a tabela de paginas na memória real. Quando o processo é trocado na memória, a tabela na memória associativa é toda invalidada (bit 0). A troca de pagina ativa é pesada, pois sempre tem que consultar a tabela de pagina. 27) PAGINAÇÃO SOB DEMANDA Capacidade de carregar paginas do disco, quando não está na memória. Nome da interrupção, falta de pagina. Paginas de código já estão no disco, não é necessário salvar novamente. Na tabela de pagina existe um outro bit, chamado de alterado, começa com zero quando vai do disco para a memória. (suporte de HW). Se o bit estiver zerado, quer dizer que o conteúdo da memória é igual ao conteúdo do disco, então, não precisa salvar novamente. Se o bit for 1, o conteúdo da memória é diferente do conteúdo do disco, então, é necessário salvar em disco pelo menos uma vez. Resumo: 1) HW tenta fazer conversão de virtual para real, mas o bit de presente da tabela de pagina está desligado. O HW gera interrupção. 2) O SO verifica se a pagina: de fato não existe, aborta o processo; precisa ser carregado na memória. 3) O SO encontra uma pagina física disponível SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 19 4) Enviar ordem para o HW para leitura da pagina virtual que está em disco para a pagina física disponível (bloqueia o processo que gerou a falta de pagina). 5) Leitura da pagina termina, o SO faz mapeamento da pagina virtual para real, mudando a tabela de paginas. 6) A interrupção termina e o HW reinicia a instrução que gerou a falta de pagina. Entre 4 e 5, demora p acontecer, a CPU escalona outro processo p rodar, o processo fica bloqueado (que gerou a falta de pagina) 27.1) Página Vitima Na tabela de paginas, a entrada correspondente a pagina escolhida como vitima, passa a ter o bit de presença 0, e o campo da pagina real correspondente fica vazio, para indicar que a pagina foi para disco, que não está na memória. A tabela auxiliar contem numero da pagina virtual no disco, sua posição em disco e o processo ao qual pertence. Ao tentar acessar essa pagina em disco, o gerenciador de memória gera uma interrupção e só ira procurar a pagina primeiramente na tabela auxiliar, para saber se está em disco. Assim, o conteúdo do disco naquela posição é copiado para a memória, mas não sai da tabela nem do disco. Tão logo a pagina é traduzida de volta para a memória, o processo volta a rodar. É a pagina física que é escolhida para ser retirada em uma falta de pagina quando não existe memória física disponível. A pagina vitima não existe quando é código e a pagina não foi alterada. Devem existir um numero mínimo de paginas para um processo rodar. 27.2) ALGORITMO DE ESCOLHA DAS PÁGINAS VITIMAS PARA MINIMIZAR O Nº DE FALTAS FIFO: Primeira página a entrar é a primeira a sair. Problema: Dependendo da seqüência de instruções acessadas, pode haver faltas demais, tornando a execução muito lenta. Algoritmo Ótimo: Escolhe para sair a página a ser utilizada no futuro mais distante. Vantagem: menos faltas que o FIFO. Desvantagem: Prever a seqüência de paginas acessadas. Página menos recentemente usada (LRU): retirado da memória as paginas com acessos menos recentes, utilizando o principio da localidade Não tem como ser implementado. Simplificação da LRU (Algoritmo Possível – Bit de Referencia): Colocar mais um bit na tabela de pagina, chamado acessado. Quando a pagina é acessada o bit se torna 1. De tempos em tempos, todos os bits são zerados pelo SO. Então todo bit fica com zero em relação aos outros que ficam com 1, quer dizer que essa pagina com bit 0 foi usada há mais tempo. Podendo ser a pagina vitima. Algoritmo do Relógio: esse algoritmo faz uso do bit de usado, que indica se uma pagina mapeada na memória foi acessada. É implementado por software, um ponteiro percorre periodicamente a tabela de pagina, zerando o bit de usado, de modo a manter uma lista de possíveis paginas vitimas, de bloco de paginas (zerar todas ao mesmo tempo demoraria muito). Na tabela de paginas, quando há falta de paginas, o ponteiro percorre a tabela de paginas zerando os bits de usado, e , ao encontrar uma pagina com bit de usado zerado (indicando que não foi recentemente usado), o ponteiro indica ao SO que aquela pagina pode ser escolhida como vitima SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 20 e ir para disco. Problema: O HW pode não ter bit de usado, se a tabela for muito grande, o ponteiro irá demorar muito para percorrê-la por inteiro. Quando o HW não dá suporte ao bit de acessado na Tabela de Pagina: É criada uma tabela de página apenas com o bit de presente e então é criada uma tabela de pagina de software com bits de „realmente presente” e acessado. A tabela de pagina com bit de presença é zerado, então, quando uma pagina é acessada, o HW gera uma interrupção e o SO acessa a tabela de pagina de software.De tempos em tempos, os bits de presença são zerados na tabela de paginas. (simulação em SW do bit de acessado da tabela de pagina). Como são muitas entradas na tabela de paginas, os bits não são zerados de uma vez só. (algoritmo da 2 chance/relógio). Existe um ponteiro na tabela de pagina, apontando para determinada pagina, se a pagina não estiver presente, o HW gera interrupção e o SO acessa a tabela de pagina auxiliar e verifica se a pagina está realmente presente, quando tenta jogar a pagina na memória real e não existe espaço, a pagina onde o ponteiro estiver apontando, se ela estiver com o bit de acessado ligado, esta pagina não será jogada para disco, mas o bit de acessado será zerado e o ponteiro irá para outra pagina. 27.3) POOL LIVRE DE PAGINAS Aproveitar o tempo ocioso da CPU, para procurar paginas vitimas e salvá-las em disco. Então haverá páginas livres na memória. Quando determinado percentual de paginas livres é alcançado, a procura de paginas vitimas é iniciada. O SO desaloca a pagina do processo e a salva em disco, deixando a pagina livre. O SO não zera o conteúdo da pagina, mantem essa informação numa tabela de controle. A informação é a seguinte: Na pagina é informado que a mesma pertencia a determinada pagina virtual de tal processo. Se o processo que gerar a falta de pagina for o mesmo da pagina que foi salva em disco, é apenas refeito o mapeamento do processo, sendo não necessário carregar o conteúdo e disco em memória. O SO escolhe para o pool de paginas livres, a pagina real 1 que contem a pagina virtual 2 do processo 2. A pagina real 1 será marcada com livre e será desmapeada do processo 2, se tiver sido alterada a pagina é salva em disco. Se o processo gerar uma falta de pagina em sua pagina virtual 2 e a pagina real 1 ainda não foi utilizada por outro processo, então, o SO simplesmente mapeia a pagina real 1, como pagina virtual 2 do processo 2. A paginação é um esquema que permite que o espaço de endereçamento físico de um processo seja não contíguo. A memória física é quebrada em blocos de tamanho fixo chamado quadros (frames). A memoria lógica também é quebrada em blocos de tamanho igual chamados páginas.Quando um processo vão ser executado, suas paginas são carregadas em qualquer quadro de memória disponível a partir do armazenamento auxiliar. O armazenamento auxiliar é dividido em blocos de tamanho fixo que tem o mesmo tamanho que os quadros de memória. Cada endereço gerado pela CPU é dividido em duas partes: um numero de pagina(p) e um deslocamento de pagina(d). O numero de pagina é usado como um índice em uma tabela de pagina. A tabela de pagina contem o endereço base de cada pagina na memória física. Esse endereço base é combinado com o deslocamento de pagina para definir o endereço de memória SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 21 física que é enviado para a unidade de memória. Todo endereço lógico é associado pelo HW de paginação a algum endereço. Quando usamos um esquema de paginação, não existe fragmentação externa: qualquer quadro livre pode ser alocado a um processo que precisa dele. No entanto, pode haver alguma fragmentação interna. Se os requisitos de memória de um processo não forem múltiplos do tamanho das paginas, o ultimo quadro alocado talvez não fique completamente cheio. Quando um processo chega no sistema para ser executado, seu tamanho, expresso em paginas, é examinado. Cada pagina do processo precisa de um quadro. Assim, se o processo precisar de n paginas, deve haver pelo menos n quadros disponíveis na memória. O programa de usuário visualiza essa memória como um único espaço contíguo, que contem apenas esse programa. Como o SO está gerenciando memória física, ele deve estar ciente dos detalhes de alocação da memória física. Essas informações são geralmente mantidas em uma estrutura chamada de Tabela de Quadros (Frame Tables). A tabela de quadros tem uma entrada para cada quatro de pagina física, indicando se está livre ou alocado e, se estiver alocado, a que pagina de qual processo ou processos. Quando um processo vai ser carregado na memória, o paginador adivinha que paginas serão usadas antes que o processo seja descarregado novamente. Em vez de carregar o processo inteiro, o paginador leva apenas as paginas necessárias para a memória. Precisamos de alguma forma de suporte de HW para fazer distinção entre as paginas que estão na memória e as que estão no disco. O esquema de bit válido-invalido pode ser usado. Desta vez, quando o bit for valido, o valor indicará que a pagina associada é legal e está na memória. Se o bit for definido para invalido, o valor indica que a pagina não é valida, ou seja, não está no espaço de endereçamento lógico do processo ou é valida mas no momento está no disco. Mas o que acontece se o processo tenta usar uma pagina que não foi carregada na memória? O acesso a uma pagina marcada como invalida causa uma interrupção da falta de pagina. O HW de paginação, ao traduzir o endereço através da tabela de pagina, observará que o bit invalido está ativo, gerando uma exceção para o SO. 27.4) PROCEDIMENTO PARA TRATAR UMA FALTA DE PAGINA SIMPLES Verificamos uma tabela interna (geralmente mantida com o bloco de controle de processo) para esse processo, a fim de determinar se a referencia foi um acesso a memória valido ou invalido. Se a referencia foi invalida, terminamos o processo. Se foi valida, mas ainda não carregamos essa pagina, agora podemos carregá-la. Encontramos um quadro livre (escolhendo um da lista de quadros livres, por exemplo). Escalonamos uma operação de disco para ler a pagina desejada no quadro recém-alocado. Quando a leitura do disco estiver pronta, modificamos a tabela interna mantida com o processo e a tabela de pagina para indicar que a pagina agora está na memória. Reiniciamos a instrução que foi interrompida pela exceção de endereço ilegal. O processo agora pode acessar a pagina como se ela sempre tivesse estado na memória. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 22 É importante observar que, como salvamos o estado (registradores, código de condição, contador de instrução) do processo interrompido quando ocorre a falta de pagina, podemos reiniciar o processo exatamente no mesmo local e estado, exceto pelo fato que a pagina desejada agora está na memória e é acessível. Quando um processo tenta acessar posições que não estão na memória, o HW gera exceções para o SO (falta de pagina). O SO lê a pagina desejada na memória e reinicia o processo como se a pagina sempre tivesse estado na memória. Paginação sob demanda pura: uma pagina só é levada para a memória quando ela for necessária. HW necessário: tabela de paginas e memória secundaria. Se nenhum quadro está livre, encontramos um que não está sendo usado no momento e o liberamos. Podemos liberar um quadro gravando seu conteúdo no espaço de swap e alterando a tabela de pagina para indicar que a pagina não está mais na memória. Agora podemos usar o quadro liberado para armazenar a pagina para a qual ocorreu a falta no processo. Modificamos a rotina de serviço de falta de pagina para incluir a substituição de pagina: Localizar a posição da pagina desejada no disco. Encontrar um quadro livre: Se houver um quadro livre, use-o. Se não houver quadros livres, use um algoritmo de substituição de pagina para selecionar um quadro vitima. Gravar a pagina vitima no disco; alterar as tabelas de pagina e quadro de acordo. Ler a pagina desejada no quadro (recém) liberado; alterar as tabelas de pagina e quadro. Retomar o processo do usuário. Observe que, se nenhum quadro estiver livre, duas transferências de pagina uma descarga e uma carga são necessárias. Essa situação dobra o tempo de serviço de falta de pagina e aumenta o tempo de acesso efetivo proporcionalmente. Podemos reduzir esse custo usando o bit de modificação (bit dirty). Cada pagina ou quadro pode ter um bit de modificação associado a ele no HW. O bit de modificação para uma pagina é ativado pelo HW sempre que qualquer palavra ou byte na pagina for alterado, indicando que a pagina foi modificada. Quando uma pagina é selecionada para substituição, examinamos seu bit de modificação. Se o bit estiver ativo, sabemos que a pagina foi modificada desde que foi lida do disco.Nesse caso, devemos gravar a pagina no disco. Se o bit de modificação não estiver ativo, no entanto, a pagina não foi modificada desde que foi carregada na memória. Com a paginação sob demanda, o tamanho do espaço de endereçamento lógico não é mais limitado pela memória física. Se tivermos um processo com 20 paginas, poderemos executá-los em 10 quadros simplesmente usando paginação sob demanda e usando um algoritmo de substituição para encontrar um quadro livre sempre que necessário. Se uma pagina que foi modificada será substituída, seu conteúdo vai ser copiado para disco. Uma referencia posterior aquela pagina causará uma falta de pagina. Nesse momento, a pagina será levada de volta a memória, substituindo talvez uma outra pagina no processo. Alem disso, quando for necessária uma substituição de pagina, precisamos selecionar os quadros a serem substituídos. Criar algoritmos apropriados para resolver esses problemas é uma tarefa importante, pq a operação de I/O de disco é uma operação cara. É escolhido como página vítima a partir dos três algoritmos descritos a seguir: FIFO, ótimo, LRU, 2ª chance e do relógio. O FIFO é escolhido a primeira página que entra na memória é a SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 23 primeira a sair da memória, é a escolhida como página vítima. O Ótimo é escolhida a página vítima que não será usada em um futuro próximo. Este algoritmo não tem como ser implementado. No LRU é analisado o passado, assim a página vítima é a que teve acesso menos recentemente. O algoritmo da 2ª Chance é uma aproximação do LRU, tem que ter na tabela de página um bit de acessado e um ponteiro percorre este bit a página que teve acesso é escolhidacomo vítima este bit é zerado. Já no algoritmo do relógio tem dois ponteiros o primeiro verifica o bit de acessado e o segundo vai zerando este bit. Assim, o primeiro ponteiro é responsável pela escolha da página vítima. Idéia básica, dividir a memória em pequenos pedaços onde o processo será sempre múltiplo de uma pagina. O tamanho da pagina é menor ou igual ao tamanho do processo. Vantagem: possibilidade de visualização de memória de 2 formas. É possível ter no modo virtual 2 paginas vizinhas, ainda que no modo real esteja totalmente separadas. Para a cPU, a visão é a virtual, ou seja, ele trabalha como se as paginas estivessem continuamente alocadas. A paginação com memória virtual elimina o problema de fragmentação de memória. A memória virtual usada pela CPU Intel é de 4GB. Como o espaço virtual é muito grande, não há problema de fragmentação de memória, já que haverá espaços livres muito grande e contínuos. Essa diferença entre o espaço real e o virtual é possível devido ao gerente de memória do HW. É ele quem faz a conversão do endereço virtual acessado para o endereço real apontado. 27.5) MEIOS DE IMPLEMENTAÇÃO DA CONVERSÃO DE ENDEREÇO VIRTUAL PARA REAL O HW tenta fazer a conversão página lógica => página física mas página não é válida. HW gera interrupção. O SO identifica se a página pertence a alguma das áreas do processo. Se não pertence: aborta o processo. Se pertence: 1) O SO encontra uma página física livre. Se não tiver uma página física disponível: 1) O SO escolhe uma página vítima. 2) O SO verifica se a página foi alterada. Caso tenha sido alterada, o SO envia ordem ao disco para salvar a página. 3) O SO envia uma ordem ao disco para ler a página lógica. 4) O SO bloqueia o processo que gerou a falta de página e escalona outro processo para usar a CPU. Quando a página for lida, o disco gera uma interrupção e o SO muda o estado do processo de bloqueado para pronto. Uma simples atribuição de valor a uma variável pode bloquear um processo pelo simples fato dessa variável estar numa página que não está na memória principal e sim no disco. Ex.: K := 5; Qualquer instrução executada altera a ordem de utilização das páginas. A página usada pela última instrução passa a ser a mais recentemente usada. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 24 Não pode ser usada uma fila indicando qual a ordem de utilização das páginas (da mais recentemente usada para a menos recentemente usada) pois há alteração da ordem das páginas a todo instante e não compensaria atualizar os ponteiros. Para resolver esse problema, foi adicionado à Tabela de Páginas o bit “acessado” que é setado para 1 quando aquela entrada da Tabela de Páginas foi acessada. De tempos em tempos esse bit é zerado em todas as tabelas de páginas de todos os processos. Isso faz com que o SO saiba quais páginas foram acessadas recentemente. O problema é que tem muitas entradas nas Tabelas de Páginas. Zerar o bit “acessado” em todas as entradas de todas as Tabelas de Página dos processos gastaria muito tempo. Um mecanismo mais eficiente é o uso de um ponteiro que percorre a Tabela de Páginas e zera o bit “acessado” de todas as entradas da Tabela de Páginas até encontrar uma entrada com o bit “acessado” igual a 0. Quando o ponteiro chega à última entrada da tabela de páginas, ele volta ao início da tabela de páginas; Se uma entrada tinha o bit “acessado” igual a 0 na 1a passagem do ponteiro e na 2a passagem a mesma entrada está com o valor 1 é porque essa entrada foi acessada enquanto o ponteiro dava uma volta. Logo ela não será escolhia como página vítima. Só as páginas que continuaram com bit “acessado” igual a 0 é que poderão ser escolhidas como vítimas. Esse algoritmo é chamado de algoritmo da 2a chance ou algoritmo do relógio. Esse algoritmo era utilizado pelas antigas versões do Unix. O problema desse algoritmo é que hoje em dia as memórias são grandes e, consequentemente, as Tabelas de Páginas contêm muitas entradas. Com isso o ponteiro demoraria a dar uma volta. Com isso, um grande número de páginas poderia ficar com o bit “acessado” setado como 1 e o algoritmo não seria capaz de saber quem ele pode pegar como página vítima. Há um outro algoritmo chamado de algoritmo do relógio de 2 ponteiros. Um ponteiro percorre a tabela zerando o bit “acessado” e o outro escolhe qual página será vítima. Esse algoritmo é usado no NT e no Unix. O que fazer no HW que não tem os bits de “alterado” e “acessado” na tabela de Páginas? Para emular o uso do bit “alterado”: a página é colocada como read only; na alteração da página, o HW gera interrupção; o SO marca a página como alterada e desliga o read only. Para emular o uso do bit “acessado” : coloca a página como “não válida” (zera o bit de validade) no acesso à página o HW gera interrupção; SO marca a página como acessada e liga o bit de validade. 27.6) ALOCAÇÃO DE PÁGINAS FÍSICAS A alocação de páginas físicas pode ser feita de duas formas: 1) Globalmente É escolhida como vítima a página de qualquer processo. 2) Localmente Uma página do próprio processo é escolhida como vítima para dar vez a outra página do próprio processo. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 25 Cada processo tem um determinado número de páginas físicas reservadas para ele. O problema da alocação local é saber qual o número de páginas físicas que deve ser reservado para cada processo. Como o SO sabe qual o número de páginas necessárias para cada processo? Denomina-se working set o conjunto de páginas lógicas necessárias para a execução de um processo. Alocação Global: Não tem associação entre processos e paginas físicas. Desvantagem: Se um processo ocupa muita memória, irá roubar memória de outros processos. Quando o processo volta a executar (que teve a memória roubada) vai gerar muitas faltas de paginas. Alocação por Processo: Cada processo tem um conjunto de paginas físicas reservadas. Se este processo gerar falta de pagina, procura-se paginas vitimas no mesmo conjunto de paginas físicas. Vantagem: Evita que processos comedores de memória roubem memória de outros processos. Desvantagem: Como saber o conjunto de paginas que deve ser alocado. 28) WORKING SET Se o número de páginas físicas reservadas para esse processo for maior ou igual ao working set, não haverá falta de páginas. Se o número de páginas físicas reservadas para esse processo for um pouco menor ao working set, haverá pouca falta de páginas. Se o número de páginas físicas reservadas para esse processo for muito menor ao working set, haverá muita falta de páginas. Se o SO perceber que o número de faltas de determinado processo for muito grande, o SO pode reservar mais páginas físicas para esse processo. Se acabar as páginas físicas, o SO diminui o número de páginas físicas alocadas para todos os processos. Se algum processo sofrer muita falta de páginas, o SO reservará mais páginas físicas para ele. O Working Set pode alterar se for executada uma outra rotina. Haverá falta de página na mudança do working set. As máquinas antigas eram lentas porque havia muita falta de página por ser necessário acessar o disco várias vezes, o que consume muito tempo. Um processo que ocupa quase toda a memória no caso da alocação global pode pegar páginas físicas de outros processos. Muitos processos em execução podem causar falta de páginas. Um processo costuma utilizar as mesmas paginas, associado a determinada rotina do processo. Minimiza o numero de faltas e só volta a gerar novas faltas quando o processo muda o working set, até que todas as paginas do working set sejam carregadas na memória, então, o numero de faltas cairá. Quanto maior o numero de processos, maior a chance da CPU estar sendo utilizada. SISTEMA OPERACIONAL II – PARTE 04 Elaboradopor Luciana SA Amancio Página 26 29) TRASHING É o nome dado à lentidão da máquina causada pelo excesso de falta de página. Alocação global (Unix) e Alocação local (NT) Como o Unix resolve o problema do Trashing? Quando o uso da CPU cai ao surgir um novo processo a competir pelo seu uso (caracterização de trashing), o Unix faz um swap de um dos processos, jogando-o em disco. Digamos que em uma memória a área do processo está disposta conforme mostra a Memória Lógica 1 da Figura 8. O que a paginação faz de diferente? Ela faz uma divisão da memória em unidades de tamanho igual que são as páginas. O tamanho da página é igual a 4 KB. Cada área tem um número inteiro de páginas. Acontece quando há pouca memória disponível. Ocorre muitas faltas de paginas, ocorrendo interrupção (o processo fica bloqueado) e o uso da CPU cai, com isso, o uso do disco aumenta muito. Para evitar isso, o UNIX, joga um processo todo para disco reduzindo o consumo de memória, aumentando o consumo de CPU. 100 30 20 10 Número de processos 1 2 3 n Uso da CPU (%) Máquina sem falta de página 100 30 20 10 Número de processos 1 2 3 n n+1 Uso da CPU (%) (%) Máquina com falta de página SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 27 Figura 8 O que tem de especial é que essa memória é uma memória ilusória (Memória Lógica). Isso não corresponde ao que existe de verdade. O chip de memória de verdade é outra memória. Conforme mostra a Memória Física Verdadeira da Figura 8. Essa outra memória que de fato existe. Ela basicamente é a memória ilusória com as páginas fora de ordem. Tudo que tem algum conteúdo na memória ilusória tem que existir no mundo verdadeiro. Então tem uma relação das páginas do mundo ilusório para o mundo real. Só que as páginas que estão no mundo ilusório aparecem no mundo real em outra ordem conforme mostra a Figura 8. Esta é a primeira diferença importante. Os processos acham que existe somente a memória ilusória. O que existe de verdade é a memória física que é a logica só que em outra ordem. As páginas da memória lógica que não tem conteúdo não são representadas na memória verdadeira. 30) VANTAGENS DA PAGINAÇÃO O primeiro ponto é o seguinte se a memória lógica não existisse de verdade é uma ilusão então ela pode começar do zero. Tem a Memoria logica 1 e a Memoria logica 2 conforme mostra a Figura 8. Para que serve esta ilusão? Cada processo tem a sua memória lógica. As páginas que tem conteúdo existem no mundo verdadeiro. As páginas que não tem conteúdo não existem no mundo verdadeiro. Com esta ilusão do processo achando que a memória é toda dele. É garantido da proteção da memória. O conteúdo do processo 2 não aparece na memória lógica do processo 1. Segundo ponto existe uma questão que é colocar na memória dois processos que estão em execução. A dificuldade é o endereçamento. O endereçamento é absoluto que o processo pode ter. Preciso usar um mecanismo para conseguir ter na memória dois processos em execução. Então tem que usar registrador de base ou usar o endereço bidimensional que é a segmentação. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 28 Cada memória lógica tem o seu endereço zero. Na hora que o compilador está compilando para linguagem de máquina ele pode assumir que o endereço inicial do processo sempre será o endereço zero. Então todo o código fonte que é compilado é compilando com esta suposição. Então esta é uma vantagem conseguir colocar dois processos na memória verdadeira sem problemas de um processo confundir sua memória com a memória de outro processo, pois para o processo acha que está sozinho na memória física só que isto só é verdade na memória lógica. Ou vantagem importante é ausência da fragmentação. Na paginação a questão da fragmentação deixe de existir se no mundo real não existe a regra da continuidade. A mesma área está separada no mundo verdadeiro. A regra de ter que alocar uma área continua na memória isto é verdade na memória lógica, mas não é verdade na memória física. As áreas do processo precisam estar continua no mundo ilusório. No mundo ilusório nunca vai ter fragmentação, pois existem milhares de páginas lógicas entre as áreas de pilha e a área de dados. Se estas áreas precisarem crescer vão poder. Para conseguir criar uma página nova no mundo ilusório precisa existir página livre no mundo verdadeiro. Se precisar criar uma área de biblioteca vai ter espaço para criar na memória lógica desde que tenha página livre na memória verdadeira. Então a fragmentação que costuma ser um problema seria não tem na paginação. Não tem na memória lógica e nem na memória física. Esta é uma grande vantagem da paginação. O somatório das paginas logicas que tem conteúdo tem que ser menor ou igual às paginas da memória física da máquina. Usando a memória diretamente existem muito problemas, por exemplo, tem que usar registrador de base. Colocando a ilusão da memória lógica no meu do caminho resolve todos estes problemas. Há muito tempo atrás o SO rodava um processo por vez. A memoria real da máquina tinha um processo só. Eram muito mais simples neste tempo as coisas. A paginação traz esta simplicidade de volta. Tem uma desvantagem a paginação que é o seguinte o número inteiro de páginas por áreas. Na paginação cada área tem sempre um número inteiro de páginas. Só que o espaço que o processo precisa utilizar não necessariamente é um múltiplo do tamanho da página (4 kb). Podemos ter um código que precise apenas de 6 KB. Como existe a regra de sempre alocar um número inteiro de páginas. Terei que alocar 2 páginas. Terei um desperdício de 2 KB que será o final da última página. Este final é chamado de Fragmento interno. Que é um problema teórico da paginação. Isto é um problema que não é muito serio. Digamos que eu tenha um código que tem o tamanho de 8192 Bytes. Neste caso, não sobra nada ocupa duas paginas certinhas. Este é o melhor caso, perda de 0 bytes. O pior caso é quando o código oculpa um byte a mais, por exemplo, 8193 Bytes. Neste caso, a perda é de 4095 bytes e a perda média é de (0 + 4095)/2 = 2047,5 bytes. SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 29 Para micro o primeiro chip da Intel que tinha este mecanismo foi o 386 e o primeiro sistema operacional que começou a usar a paginação foi o Windows 3.0. O que é esse mecanismo? Passa a existir duas formas diferentes de olhar a memória: espaço do endereçamento lógico e o espaço do endereçamento físico. Existe um mapeamento das páginas lógicas e das páginas físicas. A ordem do endereçamento lógico é diferente da ordem do endereçamento físico. E os espaços do endereçamento lógicos podem refletir no espaço do endereçamento físico. Cada processo tem o seu espaço de endereçamento lógico. Como mostra o exemplo abaixo que possui processos (1, 2 e 3) cada um com o seu espaço de endereçamento lógico. E cada processo acha que está sozinho na memória, e só vê o seu espaço de endereçamento lógico. Enquanto existir espaço disponível na memória poderá se alocado um espaço de endereçamento lógico para outros processos ou aumentar o tamanho da pilha. Tem endereços lógicos que correspondem fisicamente e têm outros que não. Hoje em dia é mecanismo mais sofisticado, mas exige muito do hardware. Hardwares antigos não são capazes de fazer a paginação. O chip da Intel desde 1985 já tem este recurso. A Microsoft começou a usar a paginação em 1994, com Windows NT, no Windows 3.1 era bem primária. Em 1995, o Windows 95. FFFF 0 Na paginação não existe mais o problema de carregamento do processo namemória, pois todo processo começa no endereço 0. O grande problema é que não basta mover memória o endereço tem que acompanhar. A segmentação é fácil com relação ao processo, já com variáveis dinâmicas não é fácil, porque tem que saber quais são os ponteiros que apontam para as variáveis e corrigir os valores destes ponteiros. SO SO Pilha Dados Código Espaço de Endereçamento Lógico ou virtual processo 1 Espaço de Endereçamento Físico SO Pilha Dados Código Espaço de Endereçamento Lógico processo 2 SO Pilha Dados Código Espaço de Endereçamento Lógico ou virtual processo 3 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 30 Na segmentação é fácil porque ao mover o processo da memória o valor do deslocamento permanece o mesmo e para obter endereço final tem continuar somando com o valor do deslocamento, mas agora com outro valor do segmento. Instrução: Mov AX,[4100] 001 000 000 000 100 Div Resto da Divisão Onde: Div = divisão por 4096 (nº da página) – Parte Alta dos bits acima; Resto da divisão = resto da divisão por 4096 (deslocamento da página) –Parte Baixa. Logo: Nº da Página Deslocamento 1 4 00001 000 000 000 100 Quem preenche a tabela de página é o sistema operacional quando aloca o processo. Cada processo tem uma tabela de página diferente. 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Válido 15 0 14 0 13 0 12 0 11 13 1 10 10 1 9 0 8 0 7 0 6 0 5 0 4 0 3 0 2 6 1 1 2 1 0 3 1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Espaço de Endereçamento Físico Tabela de Paginação Em binário (divide por 4096 = 2 12 ) SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 31 O que o hardware faz é lê a tabela acima e pegar o mapeamento da posição real na memória a cada instrução executada. Em outras palavras, quem executa a conversão de virtual para real na tabela de página é o hardware. A tabela contém o mapeamento de virtual para real. Endereço Lógico: ... 000 000 001 000 000 000 1000 Endereço Físico: ... 000 000 010 000 000 000 100 O grande problema da paginação é a ida duas vezes à memória: uma para fazer a conversão do endereço físico para o lógico e vice-versa e a outra para acessar o dado e jogar para o registrador. Por exemplo, se tenho 40000 Mb , então tenho 10 Kbytes para cada página. Isso deixa a CPU duas vezes mais lenta. A tabela de página fica no endereço físico, fica em memória e pode ocupar mais de uma página. Como esta tabela é muito grande para ficar dentro do chip da CPU então ela fica na memória no endereço física. Mecanismo muito usado nos dias de hoje. Começou a ser utilizado pelo Windows 95/NT. 20 bits + 12 bits = 32 bits 1 4 Nº Página Desloc. na Pág Conversão 20 bits 12 bits 1 4 Nº Página Desloc. na Pág Espaço de Endereçamento Lógico (EEL) do Processo 1 Espaço de Endereçamento Físico (EEF) (Memória) Espaço de Endereçamento Lógico (EEL) do Processo 2 PILHA P 1 DADOS P 1 CÓD P 1 CÓD P 1 DADOS P 1 PILHA P 2 DADOS P 2 CÓD P 1 CÓD P 1 CÓD P 2 PILHA P 1 PILHA P 2 DADOS P 2 CÓD P 2 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 32 O EEL e o EEF são divididos em páginas do mesmo tamanho (4 kb/página no caso da Intel). Vantagem: - pode ter vários espaços lógicos. - Cada processo tem seu próprio EEL. - Cada processo acha que está sozinho na memória. Ele só vê o seu EEL. Logo, não afeta o outro. - Se a pilha de um processo estourou, o SO pode alocar uma nova página lógica para a pilha do processo desde que haja uma página física disponível. - Pode ser criado quantos EEL quiser desde que haja página física disponível no EEF. Usando esse mecanismo, não há o problema da amarração de endereço pois todo processo começa no endereço 0 do EEL. Mas se houver uma instrução que referencia a memória e o número da página lógica é diferente da página física? A CPU não vai acessar um endereço errado da memória? Para resolver este problema, é necessário usar uma tabela de páginas que relacione cada página lógica a uma página física. Como funciona? Se houver uma instrução MOV AX, [4100], qual página física e deslocamento a CPU deverá acessar? 20000 = 100111000100000 em binário. Como 4096 é o tamanho de uma página física/lógica para Intel, e 4096 = 212 No. Pág. Fís. correspondente à Pág. Lógica Tabela de Páginas 4 7 9 0 9 8 7 6 5 4 3 2 1 0 0 0 1 0 0 1 0 1 1 0 Pág. Fís. Válida 9 8 7 6 5 4 3 2 1 0 Espaço de Endereçamento Físico (EEF) (Memória) PILHA P 1 DADOS P1 CÓD P 1 CÓD P 1 CÓD P 1 DADOS P 1 PILHA P 1 CÓD P 1 9 8 7 6 5 4 3 2 1 0 No. pág. Lógica Espaço de Endereçamento Lógico (EEL) do Processo 1 SISTEMA OPERACIONAL II – PARTE 04 Elaborado por Luciana SA Amancio Página 33 Então devemos separar 12 bits contando a partir da direita 20000 = 100 111000100000 em binário 100 em binário = 4 em decimal . Logo a página lógica que contém o endereço 20000 é a página 4 . Olhando na tabela de páginas, vemos que a página lógica 4 é a página real 7. Logo, o endereço real a ser utilizado será Página 7 = 1011 em binário Deslocamento 3616: 111000100000 em binário. Cada processo tem sua própria tabela . Para ver se pode ser usada uma determinada página física, deve-se verificar em todas as tabelas de páginas se aquela página física está disponível (vendo o campo Página Física e o bit de validade). A cada instrução que referencia a memória deve ser calculada a nova posição de memória. A máquina fica mais lenta mais compensa ( o HW é rápido). A tabela de página fica na memória mesmo a memória sendo mais lenta em relação a CPU pois a tabela pode ser grande e pode não caber no chip da CPU. A CPU precisa acessar a memória 2 vezes para executar uma instrução que referencia a memória. Na 1a vez ela consulta a tabela de página e faz a conversão, atualiza o endereço informado na instrução e volta a acessar a memória ou para salvar um valor ou para ler um valor. Uma máquina com 128 MB de memória e uma página de 4 KB teria uma tabela de páginas de 32 k páginas. Isso ocuparia 8 páginas na memória. Problema: Perda de velocidade por acessar a memória 2 vezes Solução: TLB Soluções para Tabela de Páginas muito grandes: Solução Via Software: - Quando a pagina virtual não esta mapeada na TLB, o HW gera uma interrupção e o software fica responsável por encontrar a pagina real correspondente. - Vantagem: HW mais simples, o HW fica livre. Mais fácil de implementar e reprogramar solução de mapeamento via software. Copia Sob Demanda. - Ao criar o processo filho, o que ocorre é o compartilhamento das áreas de dados e código pelos processos Pai e Filho. Quanto as paginas de código, não há problemas pois os dois processos são copias, mas ambos não podem alterar as mesmas variáveis na área de dados. Assim, o bit de escrita das paginas de dados permanecem zerados. Quando um dos processos tenta alterar uma pagina de dados, é gerada uma interrupção pelo HW, e o gerenciador de memória cria uma copia dessa pagina com bit de escrita 1, para que o processo passe a usar a pagina normalmente. Quando o
Compartilhar