Estudo sobre os tipos de gerenciamento do SO Linux

Autor: Silas Antônio Cereda da Silva

Introdução

Linux é um sistema operacional tipo Unix que foi desenvolvido por Linus Torvalds
inspirado no sistema Minix, que é uma versão simplificada do Unix, e
que por fim veio do sistema Multics. O Linux é um exemplo de
desenvolvimento com código aberto e de software livre. O seu código
fonte está disponível sob licença GPL para qualquer pessoa utilizar,
estudar, modificar e distribuir livremente.

Um sistema Linux é capaz de funcionar em um grande número de
arquiteturas computacionais. É utilizado em supercomputadores,
computadores pessoais e até em aparelhos celulares.

Nesse artigo discutiremos sobre o Gerenciamento de Memória,
Gerenciamento de Processos, Sistema de Arquivos e também Gerenciamento
de Entrada/Saída do Sistema Operacional Linux com finalidade de obter
um aprendizado sobre a estrutura deste sistema operacional.

Gerenciamento de memória no Linux

No Linux a memória funciona da seguinte maneira, processos que estão em
execução têm prioridade na memória, quando termina um processo e se
tiver espaço na memória, ficam resíduos desse processo na memória para
uma futura volta desse processo ser mais rápida. Caso essa 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)

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

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. O tamanho de página
é fixo.

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

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.

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.

Para amenizar esse problema, o Linux tem 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.

O sistema de arquivos do Linux

É por meio de um sistema de arquivos que ocorre a gravação e a
recuperação dos dados em um dispositivo de armazenamento em um
computador.

O sistema de arquivos é independente do hardware e da BIOS, sendo
especificado pelo software do sistema operacional no momento da
instalação do sistema ou na configuração de dispositivos de
armazenamento adicionais posteriormente à instalação. (AUGUSTO, 2005)

O sistema de arquivos do Linux era inicialmente o sistema de
arquivos do Minix. Entretanto, por causa do limite de 14 caracteres
imposto aos nomes de arquivos e do tamanho máximo de 64 MB para os
arquivos, houve prontamente interesse em melhorar o sistema de
arquivos. A primeira melhoria foi o sistema de arquivos Ext, que
permitiu nome de arquivos de 255 caracteres e arquivos de até 2GB. No
entanto ele era mais lento que o sistema de arquivos do Minix motivando
assim a continuidade das pesquisas. (TANEMBAUM, 2005)

Atualmente são mais de 20 sistemas de arquivos suportados pelo Linux, dentre eles os mais utilizados são o Ext3 e o ReiserFS.

O sistema de arquivos Ext3 foi desenvolvido pelo doutor Stephen
Tweedie e colaboradores na Red Hat, ele seria um ext2 com recurso de
journaling e passou a ser suportado na versão 2.4 do Linux. No ext3 o
journal usa uma camada chamada JDB (Journaling Block Device), que
utiliza um método diferente na recuperação de dados, ao invés de
armazenar bytes que devem ser gravados, ele armazena blocos modificados
do sistema de arquivos na memória para poder rastrear as operações que
ficaram pendentes, a vantagem é que ele não precisa lidar com a
complexidade de gravar bytes no journal e a desvantagem é que o journal
acaba ficando maior (SILVA, 2004).

O sistema de arquivos ReiserFS foi criado por Hans Reiser
especialmente para o Linux, atualmente ela é patrocinada pela SuSE e
mantida pela empresa NameSys (sendo o filesystem padrão das
distribuições GNU/Linux da SuSE), o ReiserFS não utiliza blocos de
tamanho fixo, mas ajusta o tamanho de acordo com o arquivo, ele e muito
rápido ao ler arquivos menores.

O ReiserFS possui suporte a arquivos maiores que 2GB, o acesso
a árvore de diretórios é mais rápido que o ext3, utiliza uma eficiente
estrutura de dados chamada "balanced tree" ou árvore equilibrada pois,
trata toda a partição como se fosse uma única tabela de banco de dados
contendo diretórios, arquivos e arquivos de meta-data, isso aumenta o
desempenho de aplicativos que trabalham com arquivos pequenos (são
lidos em apenas um E/S do HD), em um sistema de arquivo como ext2 o
espaço no disco e alocado em blocos que variam de 512 a 4096 bytes ou
até maior, se o arquivo exceder um múltiplo exato do tamanho do bloco
ocorrerá desperdício de espaço no disco o ReiserFS não aloca em espaços
fixos ou blocos ele aloca o tamanho exato que o arquivo precisa.

O ReiserFS infelizmente não trabalha perfeitamente com o
sistema de arquivos de rede NFS (Network File System), existem alguns
patches para resolver o problema, mas eles não o resolvem
completamente. (SILVA, 2004)

Gerenciamento de E/S

A gerência de entrada e saída no Linux é implementada através de
device drivers, um device para cada dispositivo. Os device drivers são
acoplados ao sistema operacional quando o kernel é gerado. Sempre que
um novo dispositivo é acrescentado ao sistema, o driver correspondente
deve ser acoplado ao núcleo. O acesso a dispositivos é na forma de
arquivos especiais.

No Linux, todas as operações de E/S são realizadas como uma seqüência
de bytes, não existindo o conceito de registro ou métodos de acesso.
Dessa forma, as system calls de E/S podem manipular qualquer tipo de
dispositivo de forma uniforme.

Os arquivos especiais podem ser acessados da mesma forma que qualquer
outro arquivo, utilizando simplesmente as system calls de leitura e
gravação. O Linux trabalha com dois tipos de operações de entrada e
saída: uma orientada a blocos e outra orientada a caracter.

As operações orientadas a bloco estão geralmente associadas a
dispositivos com altas taxas de transferência, como discos, e têm o
objetivo de minimizar o número de transferências entre o dispositivo e
a memória, utilizando buffer caches (vide figura a seguir). Por
exemplo, quando uma operação de leitura a disco é realizada, um bloco é
transferido para a memória e, posteriormente, processado.

Programa

Sistema de Arquivo

Buffer cachê

device driver

Disco

Dispositivos orientados a caracteres estão associados normalmente a
dispositivos lentos, como terminais, onde a taxa de transferência entre
o dispositivo e a memória é realizada caracter à caracter.

Redirecionamento de entrada e saída

O usuário pode, através do
redirecionamento de E/S, redefinir de onde um comando ou programa
receberá sua entrada e para onde enviará sua saída. A entrada de um
comando são os dados sobre os quais o comando irá operar. Estes dados
podem vir de um arquivo especificado pelo usuário, de um arquivo de
sistema, do terminal ou da saída de outro comando. A saída de um
comando é o resultado da operação que ele realiza sobre a entrada. A
saída dos comandos pode ser impressa na tela do terminal, enviada a um
arquivo, ou servir de entrada para outro comando.

Um comando Linux, normalmente requer uma entrada (em geral, um arquivo)
e uma saída, a fim de exibir os resultados. Quando nenhum nome de
arquivo é especificado, o shell admite que o teclado do usuário será
sua entrada. O teclado é considerado a entrada padrão do sistema. E
quando alguns resultados precisam ser exibidos, o shell assume que a
tela será a saída padrão do sistema.

Gerência de processos

Nos sistemas operacionais, um processo é a forma de representar um
programa em execução. É o processo que utiliza os recursos do
computador – processador, memória, etc – para a realização das tarefas
para as quais a máquina é destinada. (ALECRIM, 2005)

O modelo de gerenciamento de processos do Linux teve uma evolução notável.

Desde o seu início, auxiliado pelo modelo Bazaar1 de
desenvolvimento, esses algoritmos foram enumeras vezes criticados e
melhorados por eruditos ao redor do mundo, isso faz com que o Linux
tenha hoje um dos melhores conjuntos de algoritmos para gerenciamento
de processos já visto.

Um processo pode ser descrito como parte de um programa que
está aparentemente rodando. Este aparente existe somente pelo fato de
que determinado processo pode entrar e sair diversas vezes do
processador em um único segundo, e em um determinado momento ele pode
não estar no processador e mesmo assim aparentemente estar rodando.

Como qualquer sistema de compartilhamento de tempo o Linux
consegue dar a impressão de execução simultânea dos processos,
separando um espaço bastante curto de tempo para cada um deles. Para
ter sucesso nesta tarefa ele segue uma serie de regras que não
desperdiça tempo de hardware com operações desnecessárias e consegue
escolher qual processo deve ser executado naquele exato momento.

O que decide essa escolha no kernel é o escalonador de
processos, que em grande parte é responsável pela produtividade e
eficiência do sistema. Mais do que um simples mecanismo de divisão de
tempo, ele é responsável por uma política de tratamento dos processos
que permite os melhores resultados possíveis.

A função do "start kernel" tem a responsabilidade de criar um
thread, este é o processo de número zero, o primeiro e o ascendente de
todos os outros processos.

Esta função também é responsável por chamar a função "Init",
que por sua vez utiliza a chamada de sistema "execve" para rodar o
executável init, que será o processo número 1, mais conhecido como
init. Podemos chamar de Deus e pai de todos os outros processos, é o
segundo processo a ser criado e um dos últimos a morrer. Seus
filhos,vivem como nós seres humanos, eles nascem, se desenvolvem, tem
uma vida mais ou menos produtiva, podem ter inúmeros.

Uma das coisas que o escalonador precisa ter ciência é em qual
estado está cada processo, na estrutura que armazena os dados de cada
processo temos um array de possíveis estados onde apenas uma das opções
abaixo estará ativa.

  • TASK RUNNING – Em execução ou aguardando para ser executado.
  • TASK INTERRUPTIBLE – O processo está suspenso até que determinada condição se torne verdadeira.
  • TASK UNINTERRUPTIBLE – Como o estado anterior, exceto pelo
    fato de que o seu estado não será modificado quando receber um sinal. É
    importante para os processos que necessitam executar determinada tarefa
    sem ser interrompido.

  • TASK STOPPED – Execução do processo foi parada.
  • TASK ZOMBIE – O processo está terminado, mas o processo pai
    ainda não executou uma chamada de sistema para retornar informações
    sobre o processo morto "wait", as informações não são descartadas pois
    ainda podem ser utilizadas.

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

Os processos do Linux são preemptivos, isso significa que
quando um processo entra no estado TASK RUNNING o kernel vai checar se
existe alguma prioridade maior do que o processo corrente. Caso exista,
o processo corrente é interrompido e o que tem prioridade maior começa
a rodar.

A prioridade de um processo no Linux está em constante
alteração, o escalonador se mantém informado sobre o que os processos
estão fazendo e assim torna-se possível ajustar a prioridade. Dessa
maneira os processos que ficaram proibidos de utilizar o CPU por um
longo intervalo de tempo, tem sua prioridade incrementada
automaticamente, contrariamente os processos que passaram um longo
período dentro do CPU são penalizados tendo sua prioridade
decrementada.

O algoritmo de escalonamento do Linux funciona dividindo o
tempo do CPU em fatias. Em uma única fatia cada processo tem um tempo
especifico de duração que é computada assim que essa fatia inicia.
Geralmente processos diferentes tem tempos de execução diferentes.
Quando o tempo de execução de um processo termina ele é retirado do CPU
e outro processo que está rodando é colocado no seu lugar.

Uma fatia termina quando todos os processos esgotaram seu tempo
reservado de execução, assim o escalonador é responsável por calcular o
tempo de execução para todos os processos e uma nova fatia inicia. Para
o Linux escolher qual processo deve rodar ele precisar escolher qual
tem a prioridade maior, existem dois tipos de prioridade:

  • Prioridade Estática – Definido pelo usuário para processos que
    necessitam de tempo real, os valores variam de 1 até 99 que nunca são
    modificados pelo escalonador.

  • Prioridade Dinâmica – Esta é aplicada para os processos
    convencionais. A prioridade dinâmica dos processos convencionais é
    sempre inferior aos processos com prioridade estática. Se existir um
    processo com prioridade estática no estado TASK RUNNING nenhum processo
    dinâmico irá rodar até que ele pare de executar.

(TOLEDO, 2005)

Conclusão

Conclui-se que o sistema operacional Linux é de grande utilidade para o
usuário por ser um sistema livre e de código fonte aberto. A pesquisa
feita sobre seus gerenciamentos, memória, processos, E/S e arquivos,
foi de grande importância para descobrir um pouco mais sobre este
sistema operacional.

As informações obtidas sobre alocação de memória e
escalonamento de processos revelam que ainda há bastante assunto para
se aprofundar em futuras pesquisas deste SO.

Referências bibliográficas

AUGUSTO, K. Sistemas de arquivos EXT3 e ReiserFS no GNU/Linux. 2005.
Disponível em:
http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=2119
Acesso em: 08 nov. 2007.

SILVA, G. R. L. Se introduzindo no universo dos filesystems. 2004.
Disponível em:
http://www.slackwarebrasil.com.br/web_site/artigos/artigo_completo.php?aid=108
Acesso em 08 nov. 2007.

LIMA, S. A. de. Entendendo o gerenciamento de memória no Linux. 2007.
Disponível em:
http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=7320
Acesso em: 08 nov. 2007.

TOLEDO, M. Gerenciamento de Processos no Linux. 2005.
Disponível em:
http://www.marcelotoledo.org
Acesso em 08 nov. 2007.

TANEMBAUM, A. S. Sistemas Operacionais Modernos. 2ª Ed. 2005.

AECRIM, E. Sistema de arquivos ext3. 2003.
Disponível em:
http://www.infowester.com/printversion/linext3.php
Acesso em: 08 nov. 2007.


http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=7539

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s