modulo 2 - gerenciamento de memóriaricardobarcelar.com.br/aulas/soa/mod2-ger_memoria.pdf ·...

19
SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br 1 - Módulo 2 - GERÊNCIA DE MEMÓRIA A memória é um recurso importante que deve ser gerenciado com cuidado. Para isso a maioria dos computadores tem uma hierarquização de memória, como visto na disciplina de Arquitetura de Computadores. O trabalho do Sistema Operacional é coordenar como essas memórias serão utilizadas. Assim, a parte do Sistema Operacional que gerencia a hierarquia de memória é chamada Gerenciador de Memória, cujo trabalho é controlar as partes das memórias que estão em uso ou não, alocar e desalocar memórias aos processos quando necessário, e gerenciar a troca entre memória principal e o disco quando a memória principal é muito pequena. 1. CONCEITOS BÁSICOS Geralmente, os programas são armazenados em memórias secundárias, por serem meios não-voláteis, abundantes e de baixo custo. No entanto, o processador sempre executa instruções localizadas na memória principal, o sistema operacional deve, então, transferir dados da memória secundária para a principal com o objetivo de reduzir a quantidade de entrada e saída – I/O. A gerência de memória deve tentar manter na memória principal o maior número possível de processos residentes, permitindo maximizar o compartilhamento do processador e demais recursos computacionais. Mesmo na ausência de espaço livre, o sistema deve permitir que novos processos sejam aceitos e executados. Isto é realizado através de swapping, que é a transferência de processos residentes na memória principal para a memória secundária. O sistema também deverá permitir a execução de programas que sejam maiores que a memória física disponível, implementando técnicas através de overlay e memória virtual. Então a gerência de memória se preocupa em: - Manter na memória principal o maior número de processos residentes; - Permitir a execução de programas que sejam maiores que a memória física disponível; - Proteger áreas de memória ocupadas por cada processo, além da área de memória reservada ao Sistema Operacional. 2. ALOCAÇÃO DE MEMÓRIA CONTÍGUA (Monoprogramação) A alocação contigua simples era implementada nos primeiros sistemas operacionais na qual a memória era dividida em duas áreas, como se vê na figura 3: - Uma para o sistema operacional - Outra para o programa do usuário O problema é que neste modelo algumas vezes não existia espaço suficiente na memória para sua execução. Alguns sistemas implementavam uma proteção que impedia o programador de obter acesso à área da memória ocupada pelo sistema operacional. Dessa forma, quando o

Upload: tranminh

Post on 15-Oct-2018

212 views

Category:

Documents


0 download

TRANSCRIPT

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

1

- Módulo 2 -

GERÊNCIA DE MEMÓRIA A memória é um recurso importante que deve ser gerenciado com cuidado. Para isso a

maioria dos computadores tem uma hierarquização de memória, como visto na disciplina de Arquitetura de Computadores. O trabalho do Sistema Operacional é coordenar como essas memórias serão utilizadas. Assim, a parte do Sistema Operacional que gerencia a hierarquia de memória é chamada Gerenciador de Memória, cujo trabalho é controlar as partes das memórias que estão em uso ou não, alocar e desalocar memórias aos processos quando necessário, e gerenciar a troca entre memória principal e o disco quando a memória principal é muito pequena. 1. CONCEITOS BÁSICOS Geralmente, os programas são armazenados em memórias secundárias, por serem meios não-voláteis, abundantes e de baixo custo. No entanto, o processador sempre executa instruções localizadas na memória principal, o sistema operacional deve, então, transferir dados da memória secundária para a principal com o objetivo de reduzir a quantidade de entrada e saída – I/O.

A gerência de memória deve tentar manter na memória principal o maior número possível de processos residentes, permitindo maximizar o compartilhamento do processador e demais recursos computacionais.

Mesmo na ausência de espaço livre, o sistema deve permitir que novos processos sejam aceitos e executados. Isto é realizado através de swapping, que é a transferência de processos residentes na memória principal para a memória secundária.

O sistema também deverá permitir a execução de programas que sejam maiores que a memória física disponível, implementando técnicas através de overlay e memória virtual. Então a gerência de memória se preocupa em:

- Manter na memória principal o maior número de processos residentes; - Permitir a execução de programas que sejam maiores que a memória física disponível; - Proteger áreas de memória ocupadas por cada processo, além da área de memória

reservada ao Sistema Operacional.

2. ALOCAÇÃO DE MEMÓRIA CONTÍGUA (Monoprogramação) A alocação contigua simples era implementada nos primeiros sistemas operacionais na qual a memória era dividida em duas áreas, como se vê na figura 3:

- Uma para o sistema operacional - Outra para o programa do usuário

O problema é que neste modelo algumas vezes não existia espaço suficiente na memória para sua execução. Alguns sistemas implementavam uma proteção que impedia o programador de obter acesso à área da memória ocupada pelo sistema operacional. Dessa forma, quando o

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

2

programa fazia referência a um endereço da memória, o Sistema Operacional verificava se o endereço estava dentro dos limites permitidos. Estando fora, o sistema apresentava um erro.

Figura 1 – Erro

Figura 2 - Alocação contígua

As desvantagens da alocação contígua simples é que somente um usuário faz uso dos recursos e na maior parte dos casos sempre existirá espaço de memória livre. Assim, não é possível permitir a utilização eficiente da UCP e da memória principal, pois apenas um processo pode utilizar esses recursos. A princípio os programas são limitados ao tamanho da memória disponível.

Figura 3 - Alocação contígua

3. MULTIPROGRAMAÇÃO COM PARTIÇÕES FIXAS Em geral a monoprogramação é utilizado em computadores pequenos com Sistema Operacional bastante simples. Contudo, com freqüência é preciso permitir que vários processos executem ao mesmo tempo.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

3

Em sistemas de tempo compartilhado, ter vários processos na memória simultaneamente significa que quando um processo está bloqueado outro está usando o processador. Dessa forma, a multiprogramação aumenta a utilização da CPU. A melhor maneira de conseguir isso é dividindo a memória em n partições que poder ser feito manualmente quando o sistema é iniciado. Assim, quando um Job chega para ser executado ele será colocado em uma fila para ser alocado na menor partição capaz de armazená-lo. No entanto, pelo fato das partições serem fixas o espaço não utilizado por um job é perdido.

Figura 4 - Multiprogramação com múltiplas filas

A desvantagem de classificar os Jobs em filas de entradas separadas torna-se aparente

quando uma fila para uma partição grande está vazia e para uma partição pequena está cheia. Uma organização alternativa é manter uma única fila de entrada.

Figura 5 - Multiprogramação com fila única

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

4

Esta organização impede o desperdício de espaço em uma partição, alocando o job na partição de acordo com seu tamanho.

Em geral, Jobs pequenos são interativos, sendo assim é uma boa estratégia dispor de pelo menos uma partição pequena, a qual permitirá que jobs pequenos sejam executados sem a necessidade de alocar uma partição grande para estes Jobs.

Outra abordagem é estabelecer uma regra determinando que um job elegível para executar, não possa ser ignorado mais do que x vezes. Toda vez que é ignorado o job ganha um ponto. Uma vez adquirido certa quantia de pontos ele não pode ser ignorado novamente. 3.1. Técnica de Overlay

Na alocação contígua simples, todos os programas estão limitados ao tamanho da área de

memória principal disponível para o usuário. Uma solução encontrada para o problema é dividir o programa em módulos, de forma que seja possível a execução independente de cada módulo, utilizando uma mesma área de memória.

Considere um programa que tenha três módulos: um principal, um de cadastramento e outro de impressão, sendo os módulos de cadastramento e de impressão independentes. A independência do código significa que quando um módulo estiver na memória para execução, o outro não precisa necessariamente estar presente. O módulo principal é comum aos dois módulos; logo, deve permanecer na memória durante todo o tempo da execução do programa.

Como se vê na figura 5, a memória é insuficiente para armazenar todo o programa, que totaliza 9kb. A técnica de overlay utiliza uma área de memória comum, onde os módulos de cadastramento e de impressão poderão compartilhar a mesma área de memória (área de overlay). Sempre que um dos dois módulos for referenciado pelo módulo principal, o módulo será carregado da memória secundária para a área de overlay.

Figura 6 – Técnica de Overlay

A definição das áreas de overlay é função do programador, através de comandos

específicos da linguagem de programação utilizada. O tamanho de uma área de overlay é estabelecido a partir do tamanho do maior módulo.

A técnica de overlay tem a vantagem de permitir ao programador expandir os limites da memória principal.

2 Kb 3 Kb

4 Kb

1 kb

2 Kb

3 Kb

4 Kb

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

5

3.2 Realocação e Proteção A multiprogramação introduz dois problemas que devem ser resolvidos, a relocação e proteção. Como visto acima, jobs diferentes executarão em endereços diferentes. Quando um programa é vinculado o linkeditor deve saber em que endereço o programa deve estar na memória. Suponha que uma primeira instrução seja a chamada para um procedimento no endereço absoluto 100, produzido pelo linkeditor. Se esse programa for carregado na partição 1 esta solicitação será executada dentro do sistema operacional. Se o programa for carregado na partição 2, isso gerará uma problema conhecido por relocação. A solução é modificar as instruções enquanto o programa é carregado na memória. Para realizar a relocação o linkeditor deve incluir no programa binário uma lista ou mapa de bits, informando quais palavras do programa são endereços a serem relocados e quais instruções não devem não devem ser relocados. A relocação durante o carregamento não resolve o problema da proteção. Como os programas nesse sistema utilizam endereços absolutos de memória em vez de endereços relativos a um registrador, não há como impedir que um programa crie uma instrução que lê ou grava em qualquer parte da memória, inclusive em área de outros usuários. Uma solução alternativa para a relocação e proteção, é equipar a máquina com dois registradores especiais de hardware, chamados registrador de base e registrador de limite.

Em suma, a multiprogramação implica em um problema: - Ao mudar de partição o programa necessita ser relocado. Esta relocação implica em

correção de endereços de instruções: - Via Software (Mapa de Correções) - Via Hardware (Registrador de base) As referências a posições de memórias feitas pelos processos devem ser corrigidas segundo

o deslocamento dele dentro da memória. - Proteção: Um processo não pode invadir a memória de outros processos. Se isso acontecer programas maliciosos poderiam interferir no funcionamento de outros programas fazendo acesso direto à memória e interferindo na sua execução. 4. SWAPPING

Em sistemas operacionais que operam em lotes é muito efetivo utilizar partições fixas; cada

job é carregado em uma partição quando chega ao começo da fila e permanece na memória até que termine.

Com sistemas de compartilhamento de tempo ou computadores gráficos pessoais esta estratégia não pode ser utilizada, pois muitas vezes não há memória suficiente para armazenar todos os processos ativos. Dessa forma, os processos em excesso são mantidos no disco e trazidos de lá para execução dinamicamente.

O Swapping foi introduzido para contornar o problema da insuficiência de memória principal. É aplicado à gerência de memória para programas que esperam por memória livre para serem executados. Nesse processo são executadas duas operações:

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

6

- Swap Out: o Sistema Operacional escolhe um processo residente e o transfere para a memória secundária.

- Swap In: ocorre um processo inverso ao swap out. O programa pode continuar sua execução como se nada tivesse acontecido.

O algoritmo deve selecionar os processos com menos chances de serem executados. Para tanto, geralmente são escolhidos os processos que estão no estado de espera (estado de espera outswapped). Processos no estado de pronto também poderão ser selecionados (estado de pronto outswapped).

Figura 7 - Swapping

Sempre que o Escalonador (CPU scheduler) decide executar um processo ele chama o

Dispatcher. O Dispatcher verifica se o processo a ser executado está residente em memória, se não, ele remove (swap out) algum processo que esteja correntemente na memória principal e carrega (swap in) o processo escolhido para ser executado. Após isto o contexto do processo a ser executado é restaurado e o controle é passado ao processo que passa então a executar. 4.1. Multiprogramação com Partições Variáveis

Como visto em sistemas multiprogramados um processo não pode invadir a memória de outro processo. No caso das partições variáveis a alocação da memória é dinâmica, ou seja, é alterada à medida que os processos entram e saem da memória. A vantagem é a melhor utilização da memória em relação às partições fixas; e a desvantagem é que as trocas de processos deixam muitos espaços vazios na memória fragmentando-a. Para este problema é possível a reorganização da memória, contudo esse processo é muito demorado. Dois pontos devem ser considerados nas partições variáveis: a quantidade de memória que deve ser alocada a um processo quando ele for criado. Se o processo não puder crescer então a alocação é simples, ou seja, o Sistema Operacional aloca somente o necessário. Solução alternativa é prevenir ou alocar uma memória extra para o seu possível crescimento. Pode-se criar uma memória para variáveis dinâmicas que são alocadas e desalocadas (Heap), e outra (Stack) para variáveis locais comuns e endereços de retorno. Para que seja possível a alocação dinâmica de memória o Sistema Operacional precisa gerenciar esse processo, usando duas formas para fazer isso: - Gerenciamento de Memória com Mapa de Bits; e - Gerenciamento de Memória com Listas Encadeadas.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

7

Esses modelos serão estudados mais a frente.

Figura 8 - Multiprogramação com Partições Variáveis

O número, o tamanho e a localização das partições variam dinamicamente à medida que os

processos entram e saem da memória. 5. FRAGMENTAÇÃO

Ao longo da vida de um sistema, áreas de memória são liberadas por processos que concluem sua execução e outras áreas são alocadas por novos processos, de forma contínua. Com isso, podem surgir áreas livres (vazios ou buracos na memória) entre os processos, o que constitui um problema conhecido como fragmentação externa.

Figura 9 - Fragmentação Externa

Esse problema afeta somente as estratégias de alocação que trabalham com blocos de

tamanho variável, como a alocação contígua e a alocação segmentada. A fragmentação externa é prejudicial porque limita a capacidade de alocação de memória no sistema.

A figura 10 apresenta um sistema com alocação contígua de memória no qual ocorre fragmentação externa. Nessa figura, observa-se que existem 68 Mb de memória livre em quatro áreas separadas (A1 . . . A4), mas somente processos com até 28 Mb podem ser alocados (usando

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

8

a maior área livre, A4). Além disso, quanto mais fragmentada estiver a memória livre, maior o esforço necessário para gerenciá-la: as áreas livres são mantidas em uma lista encadeada de área de memória, que é manipulada a cada pedido de alocação ou liberação de memória.

Figura 10 - Fragmentação Externa

Pode-se enfrentar o problema da fragmentação externa de duas formas: minimizando sua

ocorrência, através de critérios de escolha das áreas a alocar, ou desfragmentando periodicamente a memória do sistema. Para minimizar a ocorrência de fragmentação externa, cada pedido de alocação deve ser analisado para encontrar a área de memória livre que melhor o atenda. Essa análise pode ser feita usando um dos seguintes critérios:

- Melhor encaixe (best-fit): consiste em escolher a menor área possível que possa atender à solicitação de alocação. Dessa forma, as áreas livres são usadas de forma otimizada, mas eventuais resíduos (sobras) podem ser pequenos demais para ter alguma utilidade.

- Pior encaixe (worst-fit): consiste em escolher sempre a maior área livre possível, de forma que os resíduos sejam grandes e possam ser usados em outras alocações.

- Primeiro encaixe (first-fit): consiste em escolher a primeira área livre que satisfaça o pedido de alocação; tem como vantagem a rapidez, sobretudo se a lista de áreas livres for muito longa.

- Próximo encaixe (next-fit): variante da anterior (first-fit) que consiste em percorrer a lista a partir da última área alocada ou liberada, para que o uso das áreas livres seja distribuído de forma mais homogênea no espaço de memória.

Uma forma de tratar a fragmentação externa consiste em desfragmentar a memória

periodicamente. Para tal, as áreas de memória usadas pelos processos devem ser movidas na memória de forma a concatenar as áreas livres e assim diminuir a fragmentação. Contudo, se não houver espaço suficiente esta movimentação vai causar um erro denominado overhead.

Ao mover um processo na memória, suas informações de alocação (registrador base ou Tabela de segmentos) devem ser ajustadas para refletir a nova posição do processo.

Obviamente, nenhum processo pode executar durante a desfragmentação. Portanto, é importante que esse procedimento seja executado rapidamente e com pouca freqüência, para não interferir nas atividades normais do sistema. Como as possibilidades de movimentação de processos podem ser muitas, a desfragmentação deve ser tratada como um problema de otimização combinatória, cuja solução ótima pode ser difícil de calcular. As figuras abaixo ilustram três possibilidades de desfragmentação de uma determinada situação de memória; as três alternativas produzem o mesmo resultado, mas apresentam custos distintos.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

9

Figura 11 - Estratégias de desfragmentação

Figura 12 - Possibilidade de desfragmentação

Além da fragmentação externa, que afeta as áreas livres entre os processos, as estratégias

de alocação de memória também podem apresentar a fragmentação interna, que pode ocorrer dentro das áreas alocadas aos processos. A figura 9 apresenta uma situação onde ocorre esse problema: um novo processo requisita uma área de memória com 4.900 Kbytes. Todavia, a área livre disponível tem 5.000 Kbytes. Se for alocada exatamente a área solicitada pelo processo (situação A), sobrará um fragmento residual com 100 Kbytes, que é praticamente inútil para o sistema, pois é muito pequeno para acomodar novos processos. Além disso, essa área residual de 100 Kbytes deve ser incluída na lista de áreas livres, o que representa um custo de gerência desnecessário. Outra possibilidade consiste em “arredondar” o tamanho da área solicitada pelo processo para 5.000 Kbytes, ocupando totalmente aquela área livre (situação B). Assim, haverá uma pequena área de 100 Kbytes no final da memória do processo, que provavelmente não será usada por ele.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

10

Figura 13 - Fragmentação Interna

A fragmentação interna afeta todas as formas de alocação; as alocações contíguas e

segmentada sofrem menos com esse problema, pois o nível de arredondamento das alocações pode ser decidido caso a caso. No caso da alocação paginada, essa decisão não é possível, pois as alocações são feitas em páginas inteiras. Assim, em um sistema com páginas de 4 Kbytes (4.096 bytes), um processo que solicite a alocação de 550.000 bytes (134,284 páginas) receberá 552.960 bytes (135 páginas), ou seja, 2.960 bytes a mais que o solicitado.

Em média, para cada processo haverá uma perda de 1/2 página de memória por fragmentação interna. Assim, uma forma de minimizar a perda por fragmentação interna seria usar páginas de menor tamanho (2K, 1K, 512 bytes ou ainda menos). Todavia, essa abordagem implica em ter mais páginas por processo, o que geraria tabelas de páginas maiores e com maior custo de gerência. 5.1. Gerenciamento de Memória com Mapa de Bits

Este tipo de gerenciamento consiste em: - Dividir a memória em unidades de alocação (o tamanho desta unidade pode variar de

poucos bytes a vários kilobytes. - Associar a cada unidade de alocação um bit de controle que diz se aquela unidade está

alocada ou não (0 para não alocada e 1 para alocada). - O conjunto de todos os bits de controle é denominado Mapa de Bits.

Para alocar a memória para um processo o Sistema Operacional deve, inicialmente,

percorrer o mapa de bits em busca de uma seqüência de 0’s que represente um espaço de memória capaz de suportar o processo, que pode ser muito demorado. 5.1.1. TAMANHO DA UNIDADE DE ALOCAÇÃO Quanto menor a unidade de alocação, maior será o mapa de bits e maior o tempo de procura do Sistema Operacional em busca de espaço disponível para carregar o processo. Contudo, maior será o aproveitamento da memória.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

11

Quanto maior a unidade de alocação, menor será o mapa de bits e menor será o tempo de procura do Sistema Operacional em busca de espaço disponível para carregar o processo. Contudo, menor será o aproveitamento da memória, pois na última posição sempre poderá sobrar muito espaço da unidade de alocação. 5.2. Gerenciamento de Memória com Listas Encadeadas Este tipo de gerenciamento consiste em: - Manter uma lista encadeada que represente a situação da memória; - Cada nó da lista pode representar um processo na memória ou um espaço na memória; - Cada nó vai ter dois vizinhos, que representarão exatamente a situação da vizinhança daquele nó na memória, ou seja: - Se o nó representa um espaço em branco os seus vizinhos deverão representar dois processos, pois na memória, um espaço em branco sempre é delimitado por processos; - Se o nó representa um processo, os seus vizinhos poderão ser espaços em branco ou processos, dependendo da situação da memória. 5.2.1. ALGORITMOS UTILIZADOS NO GERENCIAMENTO DE MEMÓRIA COM LISTAS ENCADEADAS

Firstfit: O gerenciador de memória procura na lista encadeada um nó que represente um segmento de memória livre suficientemente grande para suportar o processo que deve ser carregado. Então o segmento de memória é quebrado em duas partes, uma com o processo e o que sobrar em um novo nó que representa um segmento livre.

Nextfit: Funciona como o FirstFit, contudo quando encontra um segmento de memória apto ele guarda a posição e na próxima vez que for chamado começa a busca a partir daquele ponto.

Bestfit: Este algoritmo vasculha a lista toda à procura de um espaço que se ajuste o mais perfeitamente possível ao tamanho do processo. É o algoritmo que mais desperdiça memória dos três até aqui citados.

Worst fit: Vasculha a lista à procura do maior espaço disponível, já que tomando o maior espaço possível, o restante do espaço ainda é grande o suficiente para acomodar um novo processo. Na verdade, a simulação mostrou que esta abordagem não leva a bons resultados. 5.3. Alocação de Espaço de Troca (swap)

Espaço de troca é o espaço ocupado no disco pelos processos que aí estão guardados, pois foram retirados da memória devido a uma troca. Os algoritmos para gerenciar o espaço alocado em disco para swap são os mesmos apresentados para o gerenciamento de memória. A diferença é que em alguns sistemas, cada processo tem no disco um espaço reservado para o mesmo e na memória ele é constantemente mudado de lugar. Além disso, como os discos são dispositivos de bloco, a quantidade de espaço reservado para os processos no disco deverá ser múltipla do tamanho do bloco.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

12

6. GERENCIAMENTO DE MEMÓRIA DO LINUX

No Linux, processos que estão em execução têm prioridade na memória, quando termina um processo e havendo espaço na memória, ficam resíduos desse processo para uma futura volta desse processo ser mais rápida. Os dados não são apagados imediatamente após o encerramento da execução. Isso garante maior agilidade na execução dos processos. Caso a memória RAM esteja lotada com processos que estão em execução, aí começa a utilização da memória SWAP (troca) (LIMA, 2007). Daí a grande importância que o Linux dispensa a este espaço, ao ponto de criar uma partição exclusiva para este fim. Cada processo do Linux, em uma máquina de 32 bits, dispõe de 3GB de espaço de endereçamento virtual para si próprio, com 1GB restante reservado para suas tabelas de páginas e outros dados do núcleo. O 1GB do núcleo não é visível quando o processo executa no modo usuário, mas torna-se acessível quando o processo faz uma chamada ao núcleo. O espaço de endereçamento é gerado quando o processo é criado e sobrescrito em uma chamada ao sistema exec1. O espaço de endereçamento virtual é dividido em áreas ou regiões organizadas em páginas contíguas e homogêneas. Isso quer dizer que cada área consiste de uma série de páginas consecutivas com proteção e propriedades de paginação idênticas. O segmento de código e os arquivos mapeados são exemplos de áreas. Pode haver vazios no espaço de endereçamento virtual entre essas áreas. Qualquer referência à memória para um vazio resulta em uma falta de página fatal (Page fault). O tamanho da página é fixo.

O Linux usa um esquema de paginação de três níveis que também é empregado de maneira modificada em várias arquiteturas. Cada endereço virtual é quebrado em até quatros campos. O campo diretório é usado como índice do diretório global, sendo que existe um privado para cada processo. O valor encontrado é um ponteiro para um dos diretórios intermediários de página, o qual é indexado por um campo do endereço virtual. A entrada selecionada aponta para a tabela de página final, a indexada pelo campo página do endereço virtual. A entrada encontrada aponta para a página requisitada. No Pentium, que usa paginação em dois níveis, cada diretório intermediário de página tem somente uma entrada, de modo que, efetivamente, a entrada do diretório global é quem escolhe a tabela de página a usar. O Linux gerencia a memória usando o algoritmo companheiro, com a adição de um vetor no qual o primeiro elemento é a cabeça de uma lista de blocos com tamanho de uma unidade. O segundo elemento é a cabeça de uma lista de blocos com tamanho de duas unidades. O próximo elemento aponta para blocos de quatro unidades e assim por diante. Dessa maneira qualquer bloco de potência de dois pode ser encontrado rapidamente. A vantagem do algoritmo do companheiro é que facilita a busca de bloco livre, se for implementada com uma estrutura de árvore.

1 Relembrando, um processo pode ser:

Fork: Criar um novo processo; Wait: Aguardar o término de seu filho; Exec: Executar outro programa; Exit:Terminar sua execução;

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

13

No entanto, esse algoritmo gera uma considerável fragmentação interna, pois, se você deseja um bloco de 65 páginas, você tem de solicitar e obter um bloco de 128 páginas.

Figura 14 - Algoritmo do companheiro

A fragmentação é resolvida pelo Kernel com um processo de desfragmentação que junta

espaços preenchidos de memória que são categoricamente semelhantes. Isto é feito com uma segunda alocação de memória que obtêm blocos, usando o algoritmo

companheiro, e depois os retalha (unidades menores) para gerenciar unidades menores separadamente.

Um terceiro alocador de memória também é utilizado quando a memória solicitada precisa ser contígua somente no espaço virtual, mas não na memória física. (TANEMBAUM, 2005) Para a proteção existe um gerenciador de memória virtual evitando que processos no modo Kernel e no modo User se misturem. 6.1. Comandos no Linux para Administração de Memória

Os comandos abaixo permitem a visualização e gerenciamento da memória: Free: Mostra espaços livres e ocupados da memória RAM e SWAP. Parâmetros:

-b Visualiza os dados em bytes -k Visualiza os dados em kilobytes -m Visualiza os dados em megabytes -g Visualiza os dados em gigabytes

Como se vê na figura abaixo há 249 Mb livres de memória RAM e, portanto não há uso de

memória SWAP.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

14

Figura 15 - Comando Free

Na linha Mem é mostrada a memória física, em -/+ buffers/cache são mostrados

somente os processos que estão em execução e quanto tem disponível, ignorando os resíduos de outros processos e em SWAP é mostrada a área de troca usada. Memstat: Lista todos os processos, executáveis e Libraries partilhadas que usam memória virtual. Identifica quem está usando a memória virtual alta. De acordo com o manual do Linux, este comando tem as seguintes opções de visualização:

-w Mostra os resultados estendidos sem truncar informações em 80 colunas

A desvantagem experimentada com o comando memstat é a quantidade de informações que ele retorna. Por este motivo pode ser avaliada a praticidade de concatenar comandos com filtros específicos. Exemplo:

memstat -w | grep /var/cache

O resultado obtido mostra o consumo de memória por módulo, o nome de cada um deles e os processos ao qual está vinculado.

PMap: Reporta o mapa de memória de um determinado processo. Este comando é específico de um processo em particular. Ele poderá mostrar os módulos que são carregados nesse processo.

Para obter as informações deverá ser usado o comando ps para que seja visualizado o id do processo para depois fornecê-lo como atributo do pmap. 7. NÍVEIS DE OPERAÇÃO (RUNLEVELS) NO LINUX

No Linux e outros sistemas baseados no Unix o runlevel indica o modo de operação atual da máquina, definindo quais serviços e recursos devem permanecer ativos. O runlevel pode ser alterado a qualquer momento pelo root, através do comando telinit (# telinit 3, # telinit 5, etc.).

No Linux os runlevels são numerados de 0 a 6, como se segue: - Nível 0: O sistema está parado, nenhum processo é executado. Este modo entra em

ação quando desligamos o sistema via software. - Nível 1: É chamado de single user mode é um modo de recuperação, onde temos ativa

apenas a conta de superusuário. Não é possível usar a rede nem rodar programas gráficos. Neste modo é possível alterar as configurações do sistema, alterar as senhas dos usuários, etc.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

15

- Níveis 2 e 3: Modo de operação normal do sistema. Nestes modos o sistema inicializa em modo texto e depois de logado o usuário pode abrir o modo gráfico se desejar. A diferença entre os dois é que no modo 2 (também considerado um modo de recuperação) não existe suporte a rede.

- Nível 5: Inicialização com login em modo gráfico, default na maioria das distribuições atualmente. O nível 4 geralmente fica vago. Na maioria das distribuições ele equivale ao modo 3, enquanto em outras, como no Slackware, equivale ao modo de login gráfico.

- Nível 6: É reservado à reinicialização do sistema. Todos os serviços e programas são parados e o sistema é reinicializado via software. O nível 6 difere do nível 0, onde o sistema fica simplesmente parado, esperando ser desligado.

Existe ainda um nível especial, o nível S, que dependendo da distribuição equivale ao nível 1 ou 6.

O nível de execução atual do sistema pode ser visualizado através do comando runlevel e modificado através dos programas init ou telinit.

Quando é executado, o runlevel lê o arquivo /var/run/utmp e adicionalmente lista o nível

de execução anterior ou a letra N em seu lugar (caso ainda não tenha ocorrido a mudança do nível de execução do sistema).

No Debian, os diretórios /etc/rc0.d a /etc/rc6.d contém os links simbólicos para arquivos em /etc/init.d que são acionados pelo nível de execução correspondente.

Por exemplo, o arquivo S10sysklogd em /etc/rc2.d, é um link simbólico para /etc/init.d/sysklogd.

O Debian segue o seguinte padrão para definir se um link simbólico em /etc/rc[0-6].d iniciará ou interromperá a execução de um serviço em /etc/init.d, que é o seguinte:

- Se um link é iniciado com a letra K (kill), quer dizer que o serviço será interrompido naquele nível de execução. O que ele faz é executar o daemon em /etc/init.d seguido de stop. - Se um link é iniciado com a letra S (start), quer dizer que o serviço será iniciado naquele nível de execução (é equivalente a executar o daemon seguido de start).

Primeiro os links com a letra K são executado e depois os S. A ordem que os links são executados dependem do valor numérico que acompanha o link, por exemplo, os seguintes arquivos são executados em seqüência: S10sysklogd S12kerneld S20inetd S20linuxlogo S20logoutd S20lprng S89cron S99xdm

Note que os arquivos que iniciam com o mesmo número (S20*) são executados alfabeticamente. O nível de execução do sistema pode ser modificado usando-se o comando init ou telinit. Os seguintes níveis de execução estão disponíveis no Debian:

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

16

- 0 - Interrompe a execução do sistema. Todos os programas e daemons2 finalizados. É acionado pelo comando shutdown -h

- 1: Modo monousuário, útil para manutenção dos sistemas. - 2: Modo multiusuário (padrão do Debian) - 3: Modo multiusuário - 4: Modo multiusuário - 5: Modo multiusuário com login gráfico - 6: Reinicialização do sistema. Todos os programas e daemons são encerrados e o sistema

é reiniciado. É acionado pelo comando shutdown -r e o pressionamento de CTRL+ALT+DEL. Para listar o nível de execução atual do sistema digite: $runlevel. O runlevel deverá listar algo como: N 2

Agora para mudar para o nível de execução 1, digite: $init 3 Agora confira a mudança digitando: $runlevel Você deverá ver este resultado: 2 3

Isto quer dizer que o nível de execução anterior era o 2 e o atual é o 3.

8. GERÊNCIA DE BOOT

Em informática, boot é o termo em inglês para o processo de iniciação do computador que carrega o sistema operacional quando a máquina é ligada.

Muitos computadores podem executar apenas códigos existentes na memória de trabalho (ROM ou RAM). Os sistemas operacionais modernos são normalmente armazenados em disco rígido, CD-ROM ou outros dispositivos de armazenamento. Logo que o computador é ligado, ele não tem um sistema operacional na memória. O hardware do computador não pode fazer as ações do sistema operacional, como carregar um programa do disco. Assim, é criado um aparente problema é criado para carregar o sistema operacional na memória.

2 Daemon – Acronimo para Disk And Execution MONitor é um programa de computador que roda em background, ao invés de ser controlado diretamente por um usuário. Tipicamente, daemons têm nomes que terminam com a letra "d"; por exemplo, syslogd é o daemon que gerencia o log do sistema. Muitas vezes, um programa se torna um daemon através de um processo de fork seguido de o processo pai matar a si mesmo, fazendo com que o init adote o processo criança. Essa prática é conhecida como "fork off and die". Muitos sistemas iniciam daemons durante a inicialização do sistema. Os daemons muitas vezes têm o propósito de responder a requisições de rede, atividades de hardware, ou outros programas. Daemons também podem executar muitas outras tarefas, como executar tarefas em horários pré-determinados (como o cron). Pode também ser definido como programa que fica rodando continuamente em uma máquina, esperando uma requisição para executar alguma tarefa ou serviço.

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

17

A solução para o paradoxo está na utilização de um pequeno e especial programa, chamado sistema de iniciação, boot loader ou bootstrap. Este programa não tem a completa funcionalidade de um sistema operacional, mas é especialmente construído para que seja capaz de carregar outro programa para permitir a iniciação do sistema operacional. Freqüentemente, boot loaders de múltiplos estágios são usados. Neste caso, vários pequenos programas se complementam em seqüência até que o último deles carregue o sistema operacional.

Esse processo é o primeiro a ser executado quando o computador é ligado, sendo o boot responsável pela carga do sistema operacional na memória principal (RAM).

Nos computadores modernos o processo de iniciação começa com a execução pela CPU de um programa contido na memória ROM (o BIOS - Basic Input/Output System do IBM PC) em um endereço predefinido (a CPU é programada para executar este programa depois de um reset automaticamente). Este programa contém funcionalidades rudimentares para procurar por dispositivos que podem conter um sistema operacional e que são, portanto, passíveis de participar de um boot. Definido o dispositivo é carregado um pequeno programa de uma seção especial deste.

No segundo estágio da inicialização um pequeno programa que normalmente não é o sistema operacional, será o responsável por carregar o sistema operacional apropriado, e finalmente transferir a execução para ele. O sistema, então, irá inicializar, carregar drivers de dispositivos (device drivers) e outros programas que são necessários para a operação normal de um sistema operacional. Exemplos de programas responsáveis por estas tarefas no GNU/Linux são o GRUB e LILO.

O processo de inicialização é considerado completo quando o computador está pronto para ser operado pelo usuário. 8.1. Gerenciadores de Boot O Linux, assim como todo Sistema Operacional, precisa de um bootloader para ser carregado em memória e entrar em operação. 8.1.1. LILO

O LILO é um acrônimo para a expressão inglesa LInux LOader que, em português, significa carregador de Linux. É um bootloader, gestor de arranque ou gerenciador de Sistemas Operacionais. Permite configurar o arranque (Boot) de múltiplos sistemas operativos na mesma máquina (não simultaneamente).

Para isso, instala-se nos primeiros 512 bytes de qualquer dispositivo de armazenamento (MBR - Master Boot Record), imediatamente antes da tabela de partições. Como tal, é independente do(s) sistema(s) operacional(ais) instalado(s) e seus sistemas de arquivos, mas é, obrigatoriamente, escrito em código-máquina e fortemente dependente da plataforma.

O LILO permite escolher um de dezesseis kernels possíveis, cada um contendo opções específicas. 8.1.2. GRUB

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

18

Em computação, GNU GRUB (ou apenas GRUB) é um multi-carregador de um sistema operacional criado pelo projeto GNU. É utilizado, normalmente, quando se deseja que um computador tenha dual booting, ou seja, que o usuário possa escolher ao iniciar a máquina, um sistema operacional dentre dois ou mais sistemas instalados. Ele é um programa que pode carregar qualquer arquivo executável com um cabeçalho multi boot nos seus primeiros 8 kB.

O GNU GRUB foi desenvolvido a partir de um pacote chamado GRand Unified Bootloader, de onde deriva o acrônimo GRUB.

Atualmente em desenvolvimento, o GRUB 2 substituiu o GRUB que passou a chamar-se GRUB Legacy (ou, em português, GRUB legado).

O processo de carregamento do sistema operacional usando o GRUB segue os seguintes passos:

1. O BIOS busca um dispositivo que faça o carregamento do Sistema Operacional (normalmente um disco rígido) e move o controle para o MBR. O MBR é situado nos 512 primeiros bytes do disco;

2. O MBR contém o estágio 1 do GRUB. Dado o pequeno tamanho deste estágio, ele apenas carrega o próximo estágio do GRUB (que pode residir em qualquer lugar no disco). O estágio 1 pode carregar o estágio 1.5 ou o estágio 2 diretamente;

3. O estágio 1.5 é localizado nos 30 primeiros Kb do disco imediatamente após o MBR. O estágio 1.5 carrega o estágio 2;

4. O estágio 2 recebe o controle, e mostra ao usuário o menu com as opções de sistemas operacionais instalados no sistema;

5. O GRUB carrega na memória o kernel do Sistema Operacional escolhido e passa o controle ao kernel.

Para sistemas operacionais que o GRUB não suporta totalmente, o controle é passado para outro carregador que continua o processo até carregar o kernel em memória como é o caso do Windows em suas diversas versões.

Figura 16 - Lilo

8.1.3. CONFIGURAÇÃO DO GRUB

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

19

Em geral, o bootloader está localizado na partição ou diretório /boot do sistema Operacional GNU/Linux. Nas versões mais antigas do GRUB (GRUB Legacy) o arquivo que permite a seleção do Sistema Operacional é o /boot/grub/menu.lst.

O /boot/grub/menu.lst do GRUB legacy foi substituído por /boot/grub/grub.cfg no GRUB . O arquivo grub.cfg é atualizado automaticamente sempre que for incluída ou retirada uma versão do kernel.

As configurações do menu principal residem no arquivo /etc/default/grub. Para acrescentar entradas adicionais ao menu utilize o arquivo etc/grub.d/40_custom.

Para que as atualizações sejam efetivadas é necessário executar o update-grub. As versões mais atuais do Ubuntu utilizam o GRUB2. Informações pormenorizadas sobre a

configuração deste bootloader pode ser encontrada em https://help.ubuntu.com/community/Grub2

Figura 17 – GRUB

Outras informações técnicas acerca de gerenciadores de boot podem ser encontradas em http://www.ibm.com/developerworks/br/library/l-lpic1-v3-102-2/#3-lilo