UFF – UNIVERSIDADE FEDERAL FLUMINENSE TCE – ESCOLA DE ENGENHARIA TET – DEPARTAMENTO DE ENGENHARIA DE TELECOMUNICAÇÕES Sistemas de Computação para Telecomunicações – Turma A1 Prof. Natalia Fernandes TRABALHO 1 - UNIX GRUPO: Fernando Sérgio Cardoso Cunha Marcelo Victor Souza Paula Rodrigues Ferreira Alves SUMÁRIO 1 Motivação ................................................................................................................. 4 2 Objetivo .................................................................................................................... 4 3 O UNIX ...................................................................................................................... 4 3.1 História ............................................................................................................... 4 4 Uma Visão Geral do Sistema UNIX ........................................................................... 6 5 Estrutura do Sistema ................................................................................................ 6 5.1 O Kernel ............................................................................................................. 7 5.1.1 6 5.2 Shell .................................................................................................................... 8 5.3 Sistema de Arquivos........................................................................................... 8 5.3.1 Arquivos Comuns ........................................................................................ 9 5.3.2 Diretórios .................................................................................................... 9 5.3.3 Arquivos Especiais .................................................................................... 10 5.3.4 Estrutura Interna do Sistema de Arquivos do UNIX ................................. 11 Arquitetura do Sistema Operacional ...................................................................... 12 6.1 7 Processos .................................................................................................. 13 6.1.2 Critérios de Escalonamento...................................................................... 15 6.1.3 Escalonamento no UNIX ........................................................................... 16 Gerenciamento de Memória .................................................................................. 18 Paginação por Demanda .................................................................................. 18 7.1.1 A Chamada “fork” ..................................................................................... 20 7.1.2 A Chamada “exec” .................................................................................... 20 7.2 O Processo Paginador ...................................................................................... 21 7.3 Falta de Paginação ........................................................................................... 22 7.4 Falta de Proteção ............................................................................................. 23 POSIX....................................................................................................................... 24 8.1 9 Escalonamento................................................................................................. 13 6.1.1 7.1 8 O Núcleo (kernel) do Sistema UNIX ............................................................ 8 Versões............................................................................................................. 26 Programas de Sistema ............................................................................................ 26 10 Bibliografia .............................................................................................................. 29 2 3 1 Motivação Estudar, por meio de pesquisas, um sistema operacional específico e de grande utilização. Como consequência disto, é obtido um maior conhecimento e entendimento do conteúdo exposto em sala de aula. O Unix foi escolhido pelos integrantes, dentre muitos motivos, por ser um dos primeiros, se não o primeiro, Sistemas Operacionais de código aberto. Essa característica dá ao usuário a possibilidade de melhorar o código fonte do sistema. Uma grande motivação também é o fato de vários sistemas operacionais recentes (inclusive os que rodam em celulares) serem baseados no Unix. 2 Objetivo Descrever a estrutura do Sistema Operacional Unix, como funcionam o sistema de arquivos, o gerenciamento de memória, o escalonamento, os programas do sistema, a API de chamadas do sistema, características específicas para sistemas virtualizados, entre outros. 3 O UNIX “Atualmente, Unix (ou *nix) é o nome dado a uma grande família de Sistemas Operacionais que partilham muitos dos conceitos dos Sistemas Unix originais, sendo todos eles desenvolvidos em torno de padrões como o POSIX (Portable Operating System Interface) e outros. Alguns dos Sistemas Operacionais derivados do Unix são: BSD (FreeBSD, OpenBSD e NetBSD), Solaris (anteriormente conhecido por SunOS), IRIXG, AIX, HP-UX, Tru64, SCO, Linux (nas suas centenas de distribuições), e até o Mac OS X (baseado em um núcleo Mach BSD chamado Darwin). Existem mais de quarenta sistemas operacionais *nix, rodando desde celulares a supercomputadores, de relógios de pulso a sistemas de grande porte.” 3.1 História O Sistema UNIX foi desenvolvido no sótão de uma das mais sólidas corporações do mundo: a Bell Laboratories, o braço subsidiário de pesquisas da AT&T (Companhia americana de Telecomunicações - American Telephone and Telegraph). A maioria dos sistemas operacionais foi desenvolvida por fabricantes de computadores para venderem computadores. Considerando que a AT&T não estava no negócio de vendas de computadores , o Sistema UNIX não foi originalmente concebido como um produto comercial. Ele somente se tornou um empreendimento comercial em resposta à grande demanda que se havia desenvolvido. No final dos anos 60, a Bell Labs estava envolvida com um sistema operacional chamado Multics. O Multics é um sistema interativo de múltiplos usuários que utiliza uma CPU de computador GE. A Bell Labs retirou-se do projeto Multics em 1969, mas o Multics teve importante influência no Sistema UNIX. Na verdade, o nome UNIX teve uma relação com a palavra Multics. Uma das diferenças determinantes entre o Sistema UNIX e o Multics é a complexidade – o Sistema Operacional UNIX é relativamente simples enquanto que o Multics é extremamente complexo. 4 Mais ou menos no mesmo momento em que a Bell se retirou do projeto Multics, Ken Thompson, o “vovô do Sistema Operacional UNIX”, começou a “consertar” um minicomputador rejeitado, da Digital Equipament Corporation, o PDP-7. Ostensivamente, Thompson desejava criar um sistema operacional que pudesse apoiar os esforços coordenados de um time de programadores num ambiente de pesquisa de programação. Este objetivo foi alcançado com sucesso. Também com o objetivo de apaziguar a gerência, Thompson propôs que os próximos desenvolvimentos do sistema UNIX fossem apoiados pela Bell para fornecer uma ferramenta de preparação de documento à organização de patentes da companhia. Os esforços originais de Ken Thompson culminaram na criação de um sistema operacional, um PDP-7 montador, e vários programas utilitários em linguagem de montagem. Em 1973, Dennis Richie reescreveu o Sistema UNIX na linguagem de programação C. C é uma linguagem de programação de alto nível, de propósito geral, que foi desenvolvida por Richie. Ela provou ser adaptável a muitos tipos diferentes de arquitetura de computador. Se o Sistema UNIX não tivesse sido reescrito em uma linguagem de alto nível, ele teria sido acorrentado à máquina na qual foi desenvolvido. Um vez que os programas em linguagem de montagem originais também haviam sido escritos na linguagem C, repentinamente foi possível transportar todo o Sistema UNIX de um ambiente para o outro com um mínimo de dificuldade, apesar do sistema não ter sido originalmente destinado a ser portátil. O primeiro transporte para um tipo diferente de computador foi conseguido por Ritchie e Stephen Johnson em 1976, quando eles transportaram o Sistema UNIX para o Interdata 8/32. Enquanto Thompson ganhava a aceitação de seus colegas e da gerência durante o início dos anos 70, o Sistema UNIX começou a ser utilizado internamente através da Bell System. E enquanto a fama do sistema operacional se espalhava, gerava interesse em várias instituições acadêmicas de prestígio. Em 1975, a Western Electric começou a licenciar o Sistema UNIX. A taxa era nominal para instituições acadêmicas, encorajando muitas delas a utilizar e posteriormente desenvolver o Sistema UNIX. Começando no fim dos anos 70, uma indústria se Sistemas UNIX apareceu para fornecer hardware, software e serviços relacionados. Figura 1: Ken Thompson e Dennis Richie 5 4 Uma Visão Geral do Sistema UNIX O Unix é um sistema operacional de multitarefa preemptiva. Isso significa que, ele é capaz de executar muitas tarefas “simultaneamente”, na verdade, só um processo pode ser executado por vez em um único processador, mas eles são escalonados sequencialmente com uma velocidade altíssima, dando ao usuário a impressão que estão sendo executados ao mesmo tempo. A preempção é a forma como esses processos são escalonados na CPU, quando esgota-se um determinado intervalo de tempo (quantum), o Unix suspende a execução do processo, salva o seu contexto (conteúdo necessário para o processo ser executado) em seu PCB (Process Control Block), para que ele possa ser resgatado posteriormente do mesmo ponto onde parou, e coloca em execução o próximo processo da fila de prontos. A duração de cada processo, a sua prioridade e quando o mesmo será executado também são parâmetros determinados pelo UNIX. Uma característica importante do Unix é ser multiusuário (multiutilizador).O Unix oferece a possibilidade de vários usuários utilizarem o mesmo computador ao mesmo tempo, geralmente por meio de terminais. Cada usuário pode se conectar por um terminal (monitor, teclado e, se precisar, mouse) através de portas seriais ou conexões de rede ( mais usual hoje em dia). O Unix faz o gerenciamento dos pedidos dos usuários, e também utiliza a ideia de escalonar o(s) processador(es) entre todos eles, evitando que um utilize os recursos concedidos aos outros. Os usuários têm diferentes permissões para manipular os arquivos gerados e direito de propriedade sobre os mesmos. Quaisquer arquivos modificados pelo usuário conservarão esses direitos. Programas executados por um usuário comum estarão limitados em termos de quais arquivos poderão acessar. Dois tipos de usuários são empregados no sistema Unix: um usuário que tem privilégios de manipular qualquer recurso do hipervisor e tem a tarefa de gerenciar sistema. Esse usuário é chamado root, ou superusuário. O outro tipo são usuários comuns, esses possuem permissões restringidas. 5 Estrutura do Sistema O sistema operacional UNIX é composto de quatro partes básicas: 6 Figura 2: Estrutura do Sistema UNIX O kernel é o núcleo do sistema operacional. Ele faz interação entre o hardware do computador e Shell do UNIX. O Shell é a parte que tem a responsabilidade de comunicação com os usuários. Quando um comando é enviado por um usuário, o kernel é 'acionado' através do shell, e este, traduz o comando vindo do shell em comandos de hardware apropriados à plataforma. O sistema de arquivos é o método de armazenamento de informações utilizado pelo Unix. O Sistema UNIX contém um sistema de arquivos hierárquico. Os arquivos estão armazenados em vários níveis e o sistema de arquivos gera uma ilusão de “lugares” dentro do sistema. Os arquivos são uma sequência simples de bytes, podendo ser arquivos de textos, planilhas, arquivos binários etc. As aplicações são programas de usuários que são executados através do Shell do sistema. Essas aplicações podem ser instaladas pelo usuário através de softwares ou são fornecidas pelo próprio UNIX. 5.1 O Kernel Os computadores recebem seu kernel durante o processo de inicialização do sistema, conhecido como boot. Durante este processo, a máquina lê o kernel de um disco local e o carrega para a memória. O kernel irá residir na memória até que o sistema seja desligado. 7 5.1.1 O Núcleo (kernel) do Sistema UNIX O núcleo do Sistema UNIX é o principal gerenciador do UNIX. O núcleo escalona processos, aloca o armazenamento da memória de disco, supervisiona a transmissão de dados entre o armazenamento principal e os dispositivos periféricos e atende as solicitações de serviço dos processos. O núcleo é a parte residente da memória do Sistema Operacional UNIX. Comparado com outros sistemas operacionais, o núcleo do Sistema UNIX fornece um repertório de serviços relativamente pequeno. O núcleo nunca faz nada diretamente para um usuário, todos os serviços são fornecidos por programas utilitários que intercedem entre os usuários e o núcleo. Os programas utilitários são muito mais fáceis de serem criados, mantidos e personalizados do que o núcleo do sistema UNIX e é fácil acrescentarmos novos programas utilitários anos após o núcleo ter se tornado relativamente estável. O núcleo do Sistema UNIX contém cerca de 10.000 linhas de código C e cerca de 1.000 linhas de código de montagem. Muitos Sistemas UNIX são distribuídos com o código-fonte o núcleo e de todos os utilitários. Isto permite aos programadores estudarem e trabalharem com seu próprio sistema. Em contraste, a maioria dos outros sistemas operacionais é grande demais para ser entendida ou mantida por um indivíduo – e emendas não são permitidas. 5.2 Shell Os computadores não têm a capacidade de decifrar os comandos que foram digitados no terminal pelo usuário. A maioria dos sistemas operacionais fornece um interpretador de comandos para desempenhar esta função. O interpretador de comandos padrão do Sistema Unix é chamado de shell. Como os intérpretes que ficam entre pessoas que falam línguas diferentes, o shell fica entre usuário e o kernel. O programa shell interpreta os comandos que o kernel compreende. Ele solicita ao kernel a execução de uma tarefa para o usuário, eliminando, assim, a difícil missão da comunicação direta do usuário com o kernel em uma linguagem complicada. O Shell também contém o recurso de encadeamento de comandos, ou pipeline (canalização). Este é um recurso que possibilita o usuário conectar a saída de programa com a entrada de um outro programa. A saída de um programa flui pelo pipe e se torna a entrada do programa seguinte. Existem dois shells comumente usados: o Shell Bourne desenvolvido pela Bell Laboratories e o Shell C desenvolvido na Universidade da Califórnia, em Berkeley. 5.3 Sistema de Arquivos Um dos principais componentes de um Sistema Operacional é o Sistema de Arquivos. Um Sistema de Arquivos descreve o tipo e a organização dos dados gravados em um disco. A tarefa mais importante do UNIX é fornecer um sistema de arquivos. Arquivos são fundamentais para o UNIX de uma maneira não tratada em outros 8 sistemas operacionais. Comandos são arquivos executáveis, usualmente encontrados em locais previsíveis na árvore de diretórios. Privilégios do sistema e permissões são controlados em grande parte através de arquivos. Até mesmo a comunicação entre processos ocorre através de entidades similares a arquivos. Do ponto de vista do usuário, existem três tipos de arquivos: arquivos comuns de disco, diretórios, e arquivos especiais. 5.3.1 Arquivos Comuns Um arquivo contém qualquer informação que o usuário colocar nele, por exemplo, um programa binário ou simbólico. Nenhuma estrutura particular é esperada pelo sistema. Arquivos de texto consistem simplesmente em uma string de caracteres, com linhas demarcadas por um caractere de 'nova linha'. Programas binários são sequências de palavras, mas exatamente como eles irão aparecer no núcleo da memória quando um programa começa a executar. A estrutura dos arquivos é controlada pelos programas que usam eles, e não pelo sistema. 5.3.2 Diretórios Um diretório é um arquivo residente em disco que contém uma lista de nomes de arquivos. Cada usuário tem um diretório com seus próprios arquivos; ele pode também criar subdiretórios para contêr grupos de arquivos de seu interesse. Um diretório se comporta exatamente como um arquivo comum, exceto que ele não pode ser escrito por um programa sem privilégio, de modo que é o sistema que controla o conteúdo dos diretórios. Entretanto, qualquer usuário com permissão apropriada pode ler um diretório como qualquer outro arquivo. O sistema mantem vários diretórios para seu próprio uso. Um deles é o diretório root. Todos os arquivos no sistema podem ser encontrados traçando o caminho através de uma corrente de diretórios até que o arquivo desejado seja alcançado.Frequentemente, o ponto de começo para cada procura é o diretório root. Outro diretório do sistema contêm todos os programas fornecidos para uso geral; isto é, todos os comandos. No entanto, não é necessário que o arquivo resida neste diretório para que ele seja executado. Quando o nome do arquivo é especificado pelo sistema, ele pode estar na forma de um path name, que é uma sequência de nomes de diretórios separados por barras “/” e terminam com um nome de arquivo. Se a sequência começar com a barra, a procura começa no diretório root. O nome /alpha/beta/gamma leva o sistema a procurar do root para o diretório alpha, então ele procura de alpha para beta, para finalmente encontrar gamma em beta. Gamma pode ser um arquivo comum, um diretório, ou um arquivo especial. Como um caso limite, o nome “/” se refere a própria raiz (root). Um path name que não começando com “/” leva o sistema a começar a procura dentro do diretório corrente do usuário. De modo que, o nome alpha/beta especifica o nome do arquivo beta no subdiretório alpha do diretório corrente. O jeito mais simples de um nome, por exemplo alpha, refere-se à um arquivo onde ele mesmo é encontrado no diretório corrente.Em um outro caso limite, o nome do arquivo 'nulo' se refere ao diretório corrente. Cada diretório sempre tem pelo menos duas entradas, que são: “.” e “..”. A entrada “.” se refere ao próprio diretório. Deste modo um programa pode ler o diretório 9 corrente sob o nome “.” sem conhecer o “path name” completo. O nome “..” por convenção se refere ao pai do diretório em questão, ou seja, quem o criou. A razão para isso é simplificar a escrita dos programas que visitam subárvores da estrutura do diretório, e o mais importante, para evitar a separação das parcelas da hierarquia. 5.3.3 Arquivos Especiais Arquivos especiais constituem na característica mais incomum do sistema de arquivos do UNIX. Cada dispositivo de I/O suportado pelo UNIX é associado com pelo menos um arquivo. Arquivos especiais são lidos e escritos como arquivos comuns de disco, mas as requisições para lê-los ou escrevê-los resulta na ativação do dispositivo associado. A entrada para cada arquivo especial reside no diretório /dev. Arquivos especiais existem para cada linha de comunicação, cada disco, e para a memória de núcleo físico. É claro que, os discos ativos e o arquivo especial de núcleo são protegidos de acessos indevidos. Há uma vantagem em tratar dispositivos de I/O desse jeito: arquivo e dispositivo de I/O são tão similares quanto possível. Os nomes de arquivos e dispositivos têm a mesma sintaxe e significado, então, para um programa esperando um nome de arquivo como parâmetro pode ser passado um nome de dispositivo. Os arquivos especiais são sujeitos ao mesmo mecanismo de proteção dos arquivos comuns. O acesso a arquivos é organizado através de propriedades e proteções. Toda segurança do sistema depende, em grande parte, da combinação entre a propriedade e proteções setadas em seus arquivos e suas contas de usuários e grupos. Organização da estrutura do Sistema de Arquivos do Unix: Figura 3: Sistema de Arquivos Para descrever a estrutura interna do sistema de arquivos do UNIX, primeiramente é importante definir o que é um inodo. A parte oculta do sistema de arquivos UNIX é o inodo. Inodos estão onde a ação realmente acontece no sistema de arquivos UNIX. Há um inodo para cada arquivo. O inodo contém informações sobre a posição de um arquivo, o comprimento de um arquivo, o modo de acesso de um arquivo, as datas relevantes, o proprietário e similares. O usuário casual do Sistema UNIX está bem protegido dos inodos, pelo menos até que as estruturas de inodos se tornem inconsistentes e precisem de reparo. 10 Figura 4: Layout do Sistema de Arquivos 5.3.4 Estrutura Interna do Sistema de Arquivos do UNIX O primeiro bloco de qualquer sistema de arquivos é o bloco de inicialização. Para os sistemas de arquivos envolvidos em autocarregamento, o primeiro bloco contém um pequeno programa de autocarregamento, em caso contrário o primeiro bloco geralmente não é utilizado. O segundo bloco de um sistema de arquivos é o cabeçalho do sistema de arquivos. O cabeçalho (também chamado de superbloco) contém uma variedade de informações sobre o sistema de arquivos, o número de inodos no sistema de arquivos e vários parâmetros que se referem à lista livre. Quando um sistema de arquivos é montado (com comando mount), é feita uma entrada na tabela de montagem do núcleo do Sistema UNIX e o superbloco do sistema de arquivos é gravado em uma das grandes memórias intermediárias internas do núcleo. Os superblocos de todos os sistemas de arquivos montados estão acessíveis ao núcleo porque este necessita de informações no superbloco para acessar os arquivos e os inodos no sistema de arquivos. Os inodos são armazenados em um sistema de arquivos iniciando no bloco dois. Tamanhos diferentes de sistemas de arquivos contêm números diferentes de inodos; a contagem exata de inodos é armazenada no superbloco. Já que os inodos são fixos em tamanho e numerados consecutivamente a partir de zero, é possível localizar-se qualquer inodo dado seu número. Cada arquivo é definido por um inodo que contém todas as informações que o sistema mantém sobre este arquivo. Cada inodo contém o modo e o tipo de arquivo, o comprimento do arquivo em bytes, os números de identificação do proprietário e do grupo, a posição do arquivo e a hora em que os arquivos foram criados, modificados e acessados pela última vez. Observe que o inodo não contém o nome de um arquivo; o nome é armazenado em um diretório. A informação da posição armazenada em um inodo precisa ser armazenada em alguns detalhes. O Sistema UNIX localiza arquivos mantendo uma lista dos blocos no arquivo. Alguns sistemas operacionais localizam os arquivos mantendo o número inicial do bloco, o número final do bloco e o arquivo são armazenados contiguamente no disco. 11 Sistemas de arquivos contíguos são desagradáveis porque não podem crescer sem limite, mas são consignados pela posição inicial do próximo arquivo. Sistemas de arquivos contíguos tendem a desperdiçar espaço porque pequenos buracos entre grandes arquivos normalmente não podem ser usados até que sejam coletados durante uma operação de coleta de lixo. Mantendo uma lista de blocos num arquivo, o Sistema UNIX evita os problemas dos sistemas de arquivos contíguos. Os blocos no arquivo podem ser fisicamente espalhados pelo disco, mas logicamente os blocos formam uma longa cadeia que contém as informações no arquivo. Essas estruturas (blocos) iniciam na frente de cada sistema de arquivos e são armazenadas no disco. Já o núcleo mantém duas estruturas na memória: o superbloco de cada sistema de arquivos montado e uma tabela de inodos. O superbloco é mantido na memória porque contém vários parâmetros chave para o sistema de arquivos, incluindo mais notavelmente a posição da lista de blocos livres. Cada entrada na tabela de inodos do núcleo contém as informações chave para o acesso de um arquivo, incluindo o modo do arquivo e a posição dos blocos no arquivo. Há uma tabela restante que o núcleo mantém na memória para o acesso dos arquivos – a tabela de arquivos. Cada entrada na tabela de arquivos contém um indicador de uma determinada entrada na tabela de inodos e contém o indicador de leitura/gravação do arquivo. A área de dados por usuário de cada processo contém indicadores na tabela de arquivos de cada arquivo aberto, e a tabela de arquivos indica a tabela de inodos e esta na realidade indica o arquivo. 6 Arquitetura do Sistema Operacional Figura 5: Arquitetura do Sistema Operacional 12 6.1 Escalonamento Antes de uma abordagem direta ao escalonamento da CPU e a forma que é implementada no Sistema UNIX, é necessária a explicação sobre processos e os estados que eles podem assumir depois que são criados e prontos para a execução. 6.1.1 Processos Um processo é um programa em execução. Um processo não é somente o código do programa que o descreve, ou seja a seção de texto. Como dito anteriormente, o programa está em execução, então o processo necessita conter a atividade corrente, a sua representação do valor no contador de programa e o conteúdo dos registradores do processador. Normalmente, um processo também contém a pilha (stack) do processo, que abrange dados temporários como: parâmetros de função, endereços de retorno e variáveis locais. Uma seção dados, que contém variáveis globais, também compõe um processo, assim como um heap, que é a memória dinamicamente alocada durante o seu tempo de execução. Figura 6: Partes de um processo 6.1.1.1Estados de Um Processo Quando um processo é executado, ele muda de estado. O estado de um processo 13 é definido em parte pela atividade corrente desse processo. A forma mais simples de representar os estados de um processo é: • Novo: O processo está sendo criado. • Em execução: Instruções estão sendo executadas. • Em espera: O processo está esperando que algum evento ocorra ( como a conclusão de uma operação de I/O ou o recebimento de um sinal). • Pronto: O processo está esperando ser atribuído a um processador; • Terminado: O processo terminou sua execução. Figura 7: Estados de um processo Mas, a rigor, os estados de um processo no Sistema Operacional UNIX é mais complexo e apresenta 9 estados: 1. Executando em modo usuário; 2. Executando no modo núcleo (kernel); 3. Pronto para execução (aguardando apenas CPU) e residindo em memória primária; 4. Bloqueado (dormindo) e residindo em memória primária; 5. Pronto para execução, mas residindo em memória secundária (aguardando swapping); 6. Bloqueado (dormindo) e residindo em memória secundária; 7. O processo está saindo do modo núcleo e retornando ao modo usuário, quando ocorre uma mudança de contexto e o processo perde a CPU; 8. O processo acabou de ser criado e está em transição para “pronto”; 9. O processo executou um exit, não mais existe, mas seu registro é mantido até que seja enviado ao processo pai seu código de retorno e outras estatísticas. 14 Figura 8: Estados dos processos no UNIX 6.1.2 Critérios de Escalonamento Quando mais de um processo está ativo (pronto para executar), cabe ao sistema operacional decidir qual poderá executar primeiro. A parte do sistema operacional que toma esta decisão é chamada escalonador e o algoritmo utilizado é o algoritmo de escalonamento. Vários critérios devem ser observados por um algoritmo de escalonamento: • Progresso: garantir que cada processo tenha acesso à CPU. Evitar starvation (um processo não deve ficar eternamente esperando para ser executado); • Eficiência: manter a CPU ocupada praticamente 100% do tempo; • Tempo de resposta: minimizar o tempo de resposta na execução dos processos interativos; • Tempo de espera: minimizar o tempo de espera; 15 • Vazão: maximizar o número de processos executados por unidade de tempo. 6.1.3 Escalonamento no UNIX No UNIX há uma mistura entre Escalonamento por Prioridades e Round Robin. Esta mistura visa o desempenho da CPU em relação ao compartilhamento da mesma entre os usuários. Porém, tal algoritmo perde eficiência quando entram em questão sistemas de tempo real. O sistema divide os processos segundo duas classes de prioridades: • “Prioridades em modo núcleo (altas), referentes a processos bloqueados no estado 4 ou 5; • 7.” Prioridades em modo usuário (baixas), referentes a processos prontos no estado No caso da primeira classe de prioridades, existem dois subgrupos. O primeiro, de elevada prioridade contém os processos bloqueados a espera de swapping, I/O em disco, buffers de cache e inodes. E visando a rápida liberação de recursos do núcleo, esses processos completam suas respectivas chamadas de sistema ininterruptamente. O segundo subgrupo, de prioridade mais baixa que o primeiro, contém os processos bloqueados a espera de entrada de terminal, saída em terminal e fim de processo filho. Diferentemente do primeiro subgrupo, estes processos podem ser interrompidos, pois não agregam muitos recursos do núcleo. Por fim, processos no estado 7 são dispostos segundo um certo número de níveis de prioridade que varia de acordo com a implementação). Processos numa mesma classe de prioridade são dispostos numa fila, como representado na figura 9 pelos círculos interligados. 16 Figura 9: Prioridades e Round-Robin “O algoritmo de escalonamento do UNIX é processado segundo o seguinte esquema. Quando ocorre uma interrupção do hardware: • Caso a interrupção acorde um ou mais processos com prioridade de modo núcleo, aloque a CPU àquele de mais alta prioridade; • Caso contrário, se uma mudança de contexto se fizer necessária, aloque a CPU ao processo de mais alta prioridade dentre as de modo usuário. Em existindo mais de um processo apto a executar no mesmo nível, a seleção se dá segundo a política Round Robin. Pode-se observar que o escalonamento de processos no UNIX se dá em duas direções: por prioridades na vertical, e por Round Robin na horizontal (para processos de mesma prioridade). Outras características importantes do algoritmo de escalonamento do UNIX: • As prioridades no modo núcleo dependem apenas do evento aguardado pelo processo. • Processos transitando do modo núcleo para o modo usuário, tem seu nível de prioridade rebaixado em relação à sua posição inicial. Esta penalidade, por utilizar recursos do núcleo, visa evitar o monopólio da CPU pelos processos que utilizam chamadas de sistema de forma frequente. 17 • A cada intervalo de tempo (tipicamente um segundo), as prioridades em modo usuário são recomputadas. Processos que se utilizaram recentemente da CPU são penalizados em benefício dos processos que não a utilizaram.” 7 Gerenciamento de Memória A política de gerenciamento de memória de versões anteriores ao system V e ao 4.2 BSD era diferente da atual. Enquanto versões obsoletas utilizavam um esquema de swapping de processos, atualmente se utiliza um esquema de paginação por demanda, que será descrito a seguir. 7.1 Paginação por Demanda A instrução que requisitar uma pagina que foi carregada na memória anteriormente devera ser interrompida e carregada posteriormente quando a pagina estiver na memória. Por isso, este esquema necessita de um hardware especial. Um dos principais motivos para a utilização da memória virtual é o seu tamanho em relação a memória física. Pois a primeira é muito maior que a segunda, sendo limitada apenas pela MMU (Memory Management Unit). As estruturas principais para o gerenciamento da memória são mantidas no núcleo. São elas: Tabela de páginas, descritores de blocos, tabela de frames e tabela de uso de swap. A tabela de páginas tem dimensão fixa já que o número de páginas é igual a quantidade física de memória que cabe no tamanho da página. Esta tabela tem como entrada o número de página e possuem os seguintes campos: Endereço físico de memória que contém os dados referentes à esta página; Idade da página: por quantos ciclos esta página está ativa (na memória); copy-on-write: flag que indica que esta página está sendo compartilhada para fins de leitura, devendo ser desmembrada caso alguns dos processos que a compartilham altere seu conteúdo; Modificação: flag que indica se o processo modificou o conteúdo da página recentemente; Referência: flag que indica se o processo referenciou o conteúdo da página recentemente; Validade: flag que indica se o conteúdo da página é válido (isto é, o endereço físico guarda o conteúdo da página); Proteção: indica se o conteúdo da página é do tipo read-only ou read/write. Descritor de bloco com os seguintes campos: dispositivo de swap com área disponível para ler/gravar o conteúdo da página; número do bloco alocado à página; 18 o tipo da página: swap, arquivo executável, demand fill e demand zero (definidos mais adiante). A tabela de frames armazena dados adicionais à página: endereço físico de memória que contém os dados referentes à esta página; um contador de referência indicando quantos processos compartilham esta página em memória; O dispositivo de swap associado à página; número do bloco alocado à página. A tabela de uso de swap armazena apenas um contador de referência para indicar quantas páginas utilizam este bloco no disco. Ela é acessada pelo dispositivo de swap e número de bloco. As repetições de algumas informações acontecem para diminuir a quantidade de acessos às tabelas e assim, melhorar o desempenho da paginação. A figura 10 mostra um esquema de paginação que faz uma referência ao endereço virtual 1493K. O hardware do computador converte este endereço na página número 794. Os dados armazenados nessa página podem estar em memória ou no dispositivo de swap número 1, no bloco 2743. Para informar que o processo é o único a utilizar esta pagina, tanto em memória como em disco faz-se necessário que as tabelas de frames e de uso de swap mostrem seus contadores de referência em 1. Além disso, as tabelas de páginas e a de frames apontam para o endereço físico de memória onde os dados referentes a esta página estão armazenados. Figura 10: As várias estruturas de dados empregadas para gerenciamento de memória. 19 7.1.1 O Caso “fork” A figura 11 ilustra como ficariam as estruturas da paginação após uma chamada de sistema “fork”. Como o processo filho é uma cópia do pai e a área de texto não é duplicada, esses processos compartilharão as mesmas entradas para a tabela de páginas, que são do tipo read-only. Porém, cada um desses processos utiliza seus próprios dados, por isso as tabelas de páginas que contém as áreas de dados e de pilha são duplicadas pelo núcleo. As entradas na tabela de frames são compartilhadas pelas entradas destas tabelas e agora o contador de referência está em 2, pois esta é a quantidade de processos que fazem referência a mesma. Todas as entradas na tabela de páginas são marcadas como copy-on-write. Consequentemente, quando um dos dois processos alterar o conteúdo da página, ela deve ser desmembrada, dessa forma os endereços físicos de memória e as entradas na tabela de frames serão desmembrados. 7.1.2 O Caso “exec” Ao acionar a chamada “exec”, o programa executável é carregado do disco para a memória pelo núcleo. É possível, em um sistema paginado que o tamanho do executável seja maior que o tamanho físico da memória. Assim sendo, depois que o executável é carregado, parte dele já se encontra no dispositivo de swap. Primeiro é montada a tabela de páginas e seus respectivos descritores de blocos. O tamanho do executável é pré-reconhecido pelo sistema já que a informação está presente no cabeçalho do mesmo. As páginas são marcadas como demand zero para áreas de pilha ou demand fill para áreas de texto e dados. Após esse processo, é iniciada a cópia das regiões de dados e texto para as páginas da memória. Uma página é alocada para cada registro da tabela de página. Não estão presentes no código executável as páginas demand zero, ao invés disso, elas são alocadas e zeradas. As páginas demand fill são copiadas do disco das respectivas porções do executável. O núcleo adiciona ao inode um vetor de blocos que compõem o executável com o objetivo de copiar diretamente dele para uma página em memória. Nesta fase, o descritor de bloco da tabela de página guarda o índice do bloco no vetor que contém a porção do executável a ser carregado nesta página. Quando a parte do executável é copiada para a página, o núcleo localiza o bloco por meio de acesso ao seu índice no descritor e seu número na posição correspondente (ver figura 12). Ao ser copiado, a parte do arquivo executável vai para a memória física alocada à página, o descritor de bloco é atualizado. A partir deste momento ele contém um bloco de swap associado à página. 20 Figura 11: Situação após um fork num sistema paginado. 7.2 O Processo Paginador O processo paginador ocorre da seguinte forma. Páginas que não são referenciadas pelos processos por um longo tempo são removidas da memória. O processo começa a montar uma lista de páginas quando executado, que são candidatas à permuta (Ver figura 13). O processo paginador, então, zera o bit de referência da página. Quando o bit de referência de um vai à zero, esta vira candidata para permuta. Caso o processo paginador “passe” novamente por ela, a página é retirada da memória. É importante ressaltar que há um limite mínimo da quantidade de memória disponível para que um processo paginador seja ativado. Páginas são então removidas da memória e gravadas em disco à espera de espaço em memória. Quando uma página é grava em disco, o bit de validade da página é apagado e o seu contador de referência na tabela de frames é decrementado. Quando este contador vai à zero, o núcleo adiciona o campo da tabela de frames referente à página numa lista de páginas livres, pois apenas um único processo estava utilizando a página. O conteúdo de uma página na lista de páginas livres continua válido até que o sistema associe a página a outro processo. Estar na lista de páginas livres não significa que a página não pode ser revalidada, pois, caso um processo torne a referenciá-la, a página é removida da lista de páginas livres, tendo seu bit de validade reativado. 21 Figura 12: Lista de blocos adicionada ao inode durante a carga de um executável 7.3 Falta de Paginação A falta de paginação ocorre quando uma página que está com o bit de validade em zero é referenciada. O núcleo deve providenciar a validação da página para que o processo possa então continuar sua execução. A página referenciada pode estar num dos cinco estados abaixo. 1. 2. 3. 4. 5. No dispositivo de swap e não em memória. Em memória, na lista de páginas livres. Num arquivo executável sendo carregado. Marcada como demand fill. Marcada como demand zero. “No primeiro caso, o sistema deve alocar uma página livre e atualizar o conteúdo da memória com aquele presente no dispositivo de swap. O processo é bloqueado até que a operação de E/S se complete. 22 Figura 13: Fila de páginas candidatas a permuta No segundo caso, caso a página desde quando adicionada à lista livre não foi associada a nenhum outro processo, a página continua válida, sendo removida da lista de páginas livres sem que nenhuma operação de E/S se faça necessária. No terceiro caso, o núcleo através do descritor de bloco encontra na vetor de blocos do inode aquele que contém a parte do executável sendo requisitado. Uma operação de E/S se faz necessária para trazer o conteúdo do disco para a memória física associada à página. Neste caso, o núcleo também associa à pagina uma bloco de swap. No quarto caso, uma página é alocada, sendo seu conteúdo atualizado de forma similar ao caso anterior. Finalmente, no último caso, uma página é alocada e seu conteúdo de memória simplesmente zerado.” 7.4 Falta de Proteção Outro tipo de trap de memória ocorre quando um processo acessa uma página válida, mas os bits de proteção da página impedem o acesso. Abaixo exemplos: 1. “O processo tenta escrever numa página marcada como read-only, por exemplo, na sua própria área de texto.” 2. “O processo tenta escrever numa página marcada como copy-on-write, por exemplo, após uma chamada fork.” 23 “No primeiro caso, a falta é ilegal, sendo um sinal (tipicamente sigbus) enviado ao processo. O processo é então terminado, caso não tenha provido gerenciador para o sinal. No segundo caso, a falta é legal, mas processo é suspenso até o núcleo desmembrar a página referenciada. O núcleo providencia a alocação de uma nova página, marca-a como read/write, copia o conteúdo da página em falta para a nova página, e decrementa seu contador de referência. Se o contador vai a zero, a página marcada como copy-on-write pode ser reusada. A tabela de página do processo aponta para a nova página, agora com permissão de escrita. A partir deste ponto, o processo retoma sua execução.” 8 POSIX O projeto POSIX – Portable Operating System Interface – é uma família de normas definidas pelo IEEE e surgiu da necessidade de padronização de uma interface do sistema operacional, que tinha como objetivo garantir a portabilidade do códigofonte de um programa a partir de um sistema operacional que atenda as normas POSIX para outro sistema POSIX, desta forma as regras atuam como uma interface entre sistemas operacionais distintos. A designação internacional da norma é ISO/IEC 9945. Richard Stallman sugeriu o termo POSIX devido a um pedido da IEEE de um nome fácil de lembrar. O X tem o objetivo de representar uma herança que o sistema operacional tem do Unix. O padrão que cobre os serviços básicos dos sistemas operacionais, 1003.1, entrou em vigor em dezembro de 1990 como padrão ISO/EIC 9941-1 pela International Standard Organization (ISO) e pelo International Electrotehcnical Commssion (EIC). Este padrão foi primeiramente definido para a linguagem C e depois para Fortran e Ada. A tabela 6.1 mostra os vários grupos de trabalho envolvidos no projeto de padronização, assim como, o estado em que se encontram. Com os padrões 1003.4 (extensões em tempo real), 1003.4ª (threads) e 1003.13 (perfil do ambiente da aplicação para suporte às aplicações de tempo real), o POSIX deixou de abrigar apenas definições de interfaces para os sistemas operacionais. No entanto, a implementação fica por conta das empresas e a verificação dos dados de desempenho é realizada em laboratórios licenciados. As extensões de tempo real incluem: semáforos binários; fixação de processo na memória; 24 memória compartilhada; escalonamento preemptivo baseado em prioridade; notificação de evento assíncrono; comunicação entre processos; sistema de arquivos de tempo real. Tabela 1: Grupos representativos dos padrões de interface do IEEE para programas aplicativos. Como pode ser visto a cima, o projeto POSIX possui muitos padrões. Alguns já completos, outros em desenvolvimento e muitos ainda por vir. Isto porque o projeto segue as novas tecnologias visando atender às necessidades dos programadores. 25 8.1 Versões “ 1. POSIX.1, Serviços de núcleo (incorpora o padrão ANSI C) 2. POSIX.1b, Real-time extensions 3. Criação e controle de processos Signals[1] Exceções de Ponto Flutuante Violações de Segmentação Instruções Ilegais Erros de Barramento Timers Operações com Arquivos e Diretórios Pipes Biblioteca padrão do C I/O Controle e Interface de Portas Scheduling de Prioridade Signals de Tempo-real Clocks e Timers Semáforos Passagem de Mensagens Memória Compartilhada E/S Assícronas e Síncronas Bloqueamento(Locking) de Memória POSIX.1c, Threads extensions Criação, Controle e Limpeza de Threads Scheduling de Threads Sincronização de Threads Manipulação de Signals “ 9 Programas de Sistema Os programas de sistema, algumas vezes chamados de utilitários são programas normais executados fora do kernel do sistema operacional. Eles utilizam as mesmas chamadas de sistema disponíveis aos demais programas. Esses programas implementam tarefas básicas para a utilização do sistema e muitas vezes são confundidos com o próprio sistema operacional. Exemplos são os utilitários para a manipulação de arquivos: programas para exibir arquivos, imprimir arquivos, copiar arquivos, trocar nome de arquivo, listar o conteúdo do diretório, entre outros. 26 Uma das vantagens do Sistema Operacional UNIX é seu grande conjunto de programas utilitários. Instalações diferentes terão conjuntos diferentes de programas de sistema. Neste trabalho mostraremos e discutiremos exemplos dos utilitários mais úteis. Pwd e Cd – Diretório atual O Sistema Unix é dividido em diretórios. Em qualquer tempo dado, apenas um destes diretórios é o atual. O comando pwd revela o nome do diretório atual, enquanto para mover entre diretórios utiliza-se o comando cd. Ls – Listagem de Arquivos O comando ls é utilizado para listar os conteúdos dos diretórios e para gerar Informações sobre arquivos. O comando ls aceita muitos argumentos e opções. File – Dedução dos tipos de arquivo O comando file tenta determinar que tipo de informação é armazenada nos arquivos nomeados com argumentos. O uso mais importante do comando file é provavelmente determinar se o arquivo contem informações binárias ou de texto. Date e Who O comando date gera a data e hora atuais. Além disso, o superusuário pode invocar o comando date para ajustar a data. O comando who gera uma lista das pessoas que estão atualmente utilizando o sistema, bem como sua identificação do terminal e a hora que eles entraram no sistema. Kill – Processos de aborto de retaguarda O Sistema Unix tem um comando especial chamado kill para eliminar os processos de retaguarda. Somente o superusuário pode eliminar processos de outras pessoas. Nice – A execução de processos de baixa prioridade O comando nice é normalmente usado para reduzir a prioridade de um comando. Devemos utilizar nice sempre que estivermos fazendo processamentos importantes e quisermos reduzir as demandas sobre o sistema. 27 Time – Processos de Tempo O comando time é utilizado para marcar o tempo dos processos. Podemos controlar o tempo de um processo para comparar dois métodos diferentes ou podemos desejar saber quanto tempo algo leva para acontecer. Man – Gerar entradas do Manual O comando man é usado para gerar entradas do manual do sistema UNIX. Por exemplo, para reproduzir a entrada do manual do sistema UNIX que explica o uso do comando ls, basta inserir o comando man ls. Passwd – Mudança de senha de acesso ao sistema O comando passwd é utilizado para mudar a senha de acesso ao sistema. Algumas pessoas mudam sua senha periodicamente para manter a segurança. Echo – Repetição dos argumentos da linha de comando O comando echo repete seus argumentos. Quando os argumentos são palavras simples, o comando echo é útil para geração de mensagem no terminal. Find – Em busca de um arquivo O comando find é um auxílio para localizarmos arquivos perdidos. Ele examina a subárvore do sistema de arquivos procurando por arquivos que se associam a um conjunto de critérios. Mail – Comunicação com outros usuários O programa mail é utilizado para ler correspondências que nos é enviada ou para enviar correspondências a outros usuários ou grupos de usuários que pertençam à nossa instalação. Stty – O manipulador de terminal O comando tty é utilizado para gerar o nome do arquivo especial do terminal que está conectado à entrada padrão. Uma mensagem é listada se a entrada padrão não estiver acoplada ao terminal. 28 Du – Utilização de Discos Ocasionalmente desejamos ver quanto espaço de armazenamento em disco nossos arquivos estão ocupando. Se inserirmos o comando du teremos um resumo do número de blocos de armazenamento em disco utilizados em cada diretório na subárvore atual. Od – Despejo de arquivos O programa od é utilizado para produzir despejos de formato octal, decimal, ASCII e hexadecimal de um arquivo. Chmod – Troca de permissão de arquivos O programa chmod é utilizado para mudar as permissões do grupo, usuário ou outros, de leitura escrita ou execução do arquivo. 10 Bibliografia http://www.slideshare.net/sistemaoperacional/unix-sistema-operacional-presentation ftp://ftp.unicamp.br/pub/apoio/treinamentos/unix/unix_basico.pdf http://pt.wikipedia.org/wiki/Unix http://sup_oper.sites.uol.com.br/unix.htm http://www.daniel.prof.ufu.br/apostilas/Intr_SO2.pdf http://www.pop-rs.rnp.br/ovni/unix/Welcome.html Christian, Kaare. Sistema Operacional UNIX. Editora Campus 29