GOVERNO DO ESTADO DO RIO DE JANEIRO FUNDAÇÃO DE APOIO A ESCOLA TÉCNICA ESCOLA TÉCNICA ESTADUAL REPÚBLICA SO Sistemas Operacionais ___________________________ Curso de Informática ETE – REPÚBLICA - Rua Clarimundo de Melo, 847, Quintino Bocaiúva – Rio de Janeiro 4 ESTRUTURA DO SISTEMA OPERACIONAL 4.1 Introdução O sistema operacional é formado por um conjunto de rotinas que oferecem serviços aos usuários, ás suas aplicações, e também ao próprio sistema. Esse conjunto de rotinas é denominado núcleo do sistema ou kernel. É importante não confundir o núcleo do sistema com aplicações, utilitários ou o interpretador de comandos, que acompanham o sistema operacional (Fig.4.1). As aplicações são utilizadas pelos usuários e escondem todos os detalhes da interação com o sistema. Os utilitários, como compiladores e editores de texto, e interpretadores de comandos permitem aos usuários, administradores e desenvolvedores uma interação amigável com o sistema. Existe uma grande dificuldade em compreender a estrutura e o funcionamento de um sistema operacional, pois ele não é executado como uma aplicação tipicamente seqúencial, com inicio, meio e fim. Os procedimentos do sistema são executados concorrentemente sem uma ordem predefinida, com base em eventos dissociados do tempo (eventos assíncronos). Muitos desses eventos estão relacionados ao hardware e a tarefas internas do próprio sistema operacional. As principais funções do núcleo encontradas na maioria dos sistemas comerciais estão listadas a seguir. No decorrer do livro, estaremos abordando estas funções em detalhes: • tratamento de interrupções e exceções; • criação e eliminação de processos e threads; • sincronização e comunicação entre processos e threads; • escalonamento e controle dos processos e threads; • gerência de memória; • gerência do sistema de arquivos; • gerência de dispositivos de E/S; Fig. 4.1 Sistema computacional • suporte a redes locais e distribuídas; • contabilização do uso do sistema; • auditoria e segurança do sistema. A estrutura do sistema operacional, ou seja, a maneira corno o código do sistema é organizado e o inter-relacionamento entre seus diversos componentes, pode variar conforme a concepção do projeto. Existem diversas abordagens em relação à estrutura de sistemas operacionais que serão tratadas no decorrer do capitulo. Inicialmente serão apresentados os conceitos de system calls e do mecanismo de modos de acesso. 4.2 System Calls Uma preocupação que surge nos projetos de sistemas operacionais e a implementação de mecanismos de proteção ao núcleo do sistema e de acesso aos seus serviços. Caso uma aplicação que tenha acesso ao núcleo realize uma operação que altere sua integridade, todo o sistema poderá ficar comprometido e inoperante. As svstem calls podem ser entendidas como uma porta de entrada para o acesso ao núcleo do sistema operacional e a seus serviços. Sempre que um usuário ou aplicação desejar algum serviço do sistema, é realizada uma chamada a uma de suas rotinas através de uma svstem call (chamada ao sistema). O termo system call é tipicamente utilizado em sistemas Unix, porém em outros sistemas o mesmo conceito é apresentado com diferentes nomes, como systern services no Open VMS e Application Program Interface (API) no Windows da Microsoft. Para cada serviço disponível existe uma system call associada e cada sistema operacional tem seu próprio conjunto de chamadas, com nomes. parâmetros e formas de ativação específicos Fig. 4.2). Isto explica por que uma aplicação desenvolvida utilizando serviços de um determinado sistema operacional não pode ser podada diretamente para um outro sistema. Fig. 4.2 System call. Uma tentativa de criar uma biblioteca de chamada.s padronizadas foi proposta pelos institutos ISO e IEEE. O padrão POSIX (Portable Operating System Interface for Unix), como foi definido, permitiu que uma aplicação desenvolvida seguindo este conjunto de chamadas pudesse ser executada em qualquer sistema operacional que oferecesse suporte ao padrão. Inicialmente voltado para a unificação das diversas versões do sistema Unix, o POSIX foi incorporado, posteriormente, pela maioria dos sistemas operacionais modernos. Através dos parâmetros fornecidos na system call, a solicitação é processada e uma resposta é retornada á aplicação juntamente com um estado de conclusão indicando se houve algum erro. O mecanismo de ativação e comunicação entre o programa e o sistema operacional é semelhante ao mecanismo implementado quando um programa chama uma sub-rotina. As system calls podem ser divididas por grupos de funcão (Tabela 4.1). A maioria dos programadores e usuários desconhece os detalhes envolvidos, por exemplo, em um simples comando de leitura a um arquivo utilizando uma linguagem de alto nível. De forma simplificada, o comando da linguagem de alto nível é convertido pelo compilador para uma chamada a uma svstem call especifica, que, quando executada, verifica a ocorrência de erros e retorna os dados ao programa de forma transparente ao usuário. 4.3 Modos de Acesso Existem certas instruções que não podem ser colocadas diretamente á disposição das aplicações, pois a sua utilização indevida ocasionaria sérios problemas à integridade do sistema. Suponha que uma aplicação atualize um arquivo em disco. O programa, por si só não pode especificar diretamente as instruções que acessam seus dados no disco. Como o disco é um recurso compartilhado, sua utilização deverá ser gerenciada unicamente pelo sistema operacional, evitando que a aplicação possa ter acesso a qualquer área do disco indiscriminadamente. O que poderia comprometer a segurança e integridade do sistema de arquivos. Tabela 4.1 Funções das system call Funções System calls Gerência de processos e threads Criação e eliminação de processos e threads Alteração das características de processos e threads Sincronização e comunicação entre processos e threads Obtenção de informações sobre processos e threads Gerência de memória Alocação e desalocação de memória Gerência do sistema de arquivos Criação e eliminação de arquivos e diretórios Alteração das características de arquivos e diretórios Abrir e fechar arquivos Leitura e gravação em arquivos Obtenção de informações sobre arquivos e diretórios Gerencia de dispositivos Alocação e desalocação de dispositivos Operações de entrada/saída em dispositivos Obtenção de informações sobre dispositivos Como visto, fica claro que existem certas instruções que só devem ser executadas pelo sistema operacional ou sob sua supervisão, impedindo, assim a ocorrência de problemas de segurança e integridade do sistema. As instruções que têm o poder de comprometer o sistema são conhecidas como instruções privilegiadas, enquanto as instruções não privilegiadas são as que não oferecem risco ao sistema. Para que uma aplicação possa executar uma instrução privilegiada, é necessário que no processador seja implementado o mecanismo de proteção conhecido como modos de acesso. Existem. basicamente, dois modos de acesso implementados pelos processadores: modo usuário e modo kernel. Quando o processador trabalha no modo usuário, uma aplicação só pode executar instruções nãoprivilegiadas, tendo acesso a um número reduzido de instruções, enquanto no modo kernel ou supervisor a aplicação pode ter acesso ao conjunto total de instruções do processador. O modo de acesso de uma aplicação é determinado por um conjunto de bits localizado no registrador de status do processador, ou PSW, que indica o modo de acesso corrente. Através desse registrador, o hardware verifica se a instrução pode ou não ser executada pela aplicação. A melhor maneira de controlar o acesso as instruções privilegiadas é permitir que apenas o sistema operacional tenha acesso a elas. Sempre que uma aplicação necessita executar uma instrução privilegiada, a solicitação deve ser realizada através de uma chamada a uma system call, que altera o modo de acesso do processador do modo usuário para o modo kernel. Ao término da execução da rotina do sistema, o modo de acesso retorna para o modo usuário (fig. 4.3). Caso uma aplicação tente executar uma instrução privilegiada diretamente em modo usuário, o processador sinalizará um erro, uma exceção é gerada e a execução do programa é interrompida. Utilizando o mesmo problema do acesso ao disco apresentado, para o programa atualizar um arquivo em disco a aplicação deve solicitar a operação de E/S ao sistema operacional por meio de uma system call, que altera o modo de acesso do processador de usuário para kernel. Após executar a rotina de leitura, o modo de acesso volta ao estado usuário para continuar a execução do programa. Fig. 4.3 Chamada a uma rotina do sistema O mecanismo de modos de acesso também é uma boa forma de proteger o próprio núcleo do sistema residente na memória principal. Suponha que uma aplicação tenha acesso a áreas de memória onde está o sistema operacional. Qualquer programador malintencionado ou um erro de programação poderia gravar nesta área, violando o sistema. Com o mecanismo de modos de acesso, para uma aplicação escrever numa área onde resida o sistema operacional o programa deve estar sendo executado no modo kernel. 4.4 Arquitetura Monolítica A arquitetura monolítica pode ser comparada com uma aplicação formada por vários módulos que são compilados separadamente e depois linkados, formando um grande e único programa executável, onde os módulos podem interagir livremente. Os primeiros sistemas operacionais foram desenvolvidos com base neste modelo, o que tornava seu desenvolvimento e, principalmente, sua manutenção bastante difíceis. Devido a sua simplicidade e bom desempenho, a estrutura monolítica foi adotada no projeto do MS-DOS e nos primeiros sistemas Unix. 4.5 Arquitetura de Camadas Com o aumento da complexidade e do tamanho do código dos sistemas operacionais, técnicas de programação estruturada e modular foram incorporadas ao seu projeto. Na arquitetura de camadas, o sistema é dividido em níveis sobrepostos. Cada camada oferece um conj unto de funções que podem ser utilizadas apenas pelas camadas superiores. O primeiro sistema com base nesta abordagem foi o sistema THE (Technische Hogeschool Eindhoven), construído por Dijkstra, na Holanda, em 1968, e que utilizava seis camadas. Posteriormente, os sistemas MULTICS e Open VMS também implementaram o conceito de camadas, sendo estas concêntricas (Fig.4.5). Neste tipo de implementação, as camadas mais internas são mais privilegiadas que as mais externas. Fig 4.4 Arquitetura monolítica. A vantagem da estruturação em camadas é isolar as funções do sistema operacional, facilitando sua manutenção e depuração, além de criar uma hierarquia de níveis de modos de acesso, protegendo as camadas mais internas. Uma desvantagem para o modelo de camadas é o desempenho. Cada nova camada implica uma mudança no modo de acesso. Por exemplo, no caso do Open VMS, para se ter acesso aos serviços oferecidos pelo kernel é preciso passar por três camadas ou três mudanças no modo de acesso. Atualmente, a maioria dos sistemas comerciais utiliza o modelo de duas camadas, onde existem os modos de acesso usuário (não-privilegiado) e kernel (privilegiado). A maioria das versões do Unix e do Windows 2000 da Microsoft estão baseados neste modelo. Fig 4.5 Arquitetura em camada do OpenVMS 4.6 Máquina Virtual Um sistema computacional é formado por níveis, onde a camada de uiveI mais baixo é o hardware. Acima desta camada encontramos o sistema operacional, que oferece suporte para as aplicações, como visto na Fig. 4.1. O modelo de máquina virtual, ou virtual machine (VM), cria um nível intermediário entre o hardware e o sistema operacional, denominado gerência de máquinas virtuais (Fig. 4.6). Este nível cria diversas maquinas virtuais independentes, onde cada unia oferece uma cópia virtual do hardware, incluindo os modos de acesso, interrupções, dispositivos de E/S etc. Como cada máquina virtual é independente tias demais, é possível que cada VM tenha seu próprio sistema operacional e que seus usuários executem suas aplicações como se todo o computador estivesse dedicado a cada um deles. Na década de 1960, a IBM implementou este modelo no sistema VM/370, permitindo que aplicações batch, originadas de antigos sistemas OS/360, e aplicações de tempo compartilhado pudessem conviver na mesma máquina de forma transparente a seus usuários e aplicações. Além de permitir a convivência de sistemas operacionais diferentes no mesmo computador, este modelo cria o isolamento total entre cada VM, oferecendo grande segurança para cada máquina virtual. Se, por exemplo, uma VM executar uma aplicação que comprometa o funcionamento do seu sistema operacional, as demais máquinas virtuais não sofrerão qualquer problema. A desvantagem desta arquitetura é a sua grande complexidade, devido à necessidade de se compartilhar e gerenciar os recursos do hardware entre as diversas VMs. Outro exemplo de utilização desta arquitetura ocorre na linguagem Java, desenvolvida pela Sun Microsystems. Para se executar um programa um programa é necessario uma máquina virtual Java (Java Virtual Machine JVM). Qualquer sistema operacional pode suportar urna aplicação Java. desde que exista urna JVM desenvolvida para ele. Desta forma, a aplicação não precisa ser recompilada para cada sistema computacional. tornando-se independente do hardware e sistema operacional utilizados (Fig. 4.7). A desvantagem deste modelo é o seu menor desempenho se comparado a uma aplicação compilada e executada diretamente em urna arquitetura especifica. Fig. 4.6 Máquina Virtual. 4.7 Arquitetura Microkernel Uma tendência nos sistemas operacionais modernos é tomar o núcleo do sistema operacional o menor e mais simples possível. Para implementar esta idéia, os serviços do sistema são disponibilizados através de processos, onde cada um é responsável por oferecer um conjunto específico de funções, como gerência de arquivos. gerência de processos, gerência de memória e escalonamento. Sempre que uma aplicação deseja algum serviço, é realizada urna solicitação ao processo responsável. Neste caso, a aplicação que solicita o serviço é chamada de cliente, enquanto o processo que responde à solicitação é chamado de servidor. Um cliente, que pode ser uma aplicação de um usuário ou um outro componente do sistema operacional. solicita um serviço enviando urna mensagem para o servidor O servidor responde ao cliente através de urna outra mensagem. A principal função do núcleo é realizar a comunicação, ou sela, a troca de mensagens entre cliente e servidor (Fig. 4.8). O conceito de arquitetura microkernel surgiu no sistema operacional Mach, na década de 1980, na Universidade Carnegie-Mellon. O núcleo do sistema Mach oferece basicamente quatro serviços: gerência de processos, gerência de memória, comunicação por troca de mensagens e operações de E/S, todos em modo usuário. A utilização deste modelo permite que os servidores executem em modo usuário, ou seja, não tenham acesso direto a certos componentes do sistema. Apenas o núcleo do sistema, responsável pela comunicação entre clientes e servidores, executa no modo kernel. Como conseqüência, se ocorrer um erro em um servidor, este poderá parar, mas o sistema não ficará inteiramente comprometido, aumentando assim a sua disponibilidade. Fig. 4.7 máquina Virtual Java Como os servidores se comunicam através de trocas de mensagens, não importa se os clientes e servidores são processados em um sistema com um único processador, com múltiplos processadores (fortemente acoplado) ou ainda em um ambiente de sistema distribuído (fracamente acoplado). A implementação de sistemas microkernel em ambientes distribuídos permite que um cliente solicite um serviço e a resposta sela processada remotamente. Esta característica permite acrescentar novos servidores á medida que o número de clientes aLimenta, conferindo uma grande escalabilidade ao sistema operacional. Além disso. a arquitetura microkernel permite isolar as funções do sistema operacional por diversos processos servidores pequenos e dedicados a serviços específicos, tomando o núcleo menor, mais fácil de depurar e, conseqüentemente, aumentando sua confiabilidade. Na arquitetura microkernel, o sistema operacional passa a ser de mais fácil manutenção, flexível e de maior portabilidade. Apesar de todas as vantagens deste modelo, sua implementação, na prática, é muito difícil. Primeiro existe o problema de desempenho, devido á necessidade de mudança de modo de acesso a cada comunicação entre clientes e servidores. Outro problema e que cenas funções do sistema operacional exigem acesso direto ao hardware, como operações de E/S. Na realidade, o que é implementado mais usualmente é uma combinação do modelo de camadas com a arquitetura microkernel. O núcleo do sistema, além de ser responsável pela comunicação entre cliente e servidor, passa a incorporar outras funções críticas do sistema, como escalonamento, tratamento de interrupções e gerência de dispositivos. Existem vários projetos baseados em sistemas microkernel, principalmente em instituições de ensino e centros de pesquisa, como o Exokernel, do MIT (Massachusetts Institute of Technology); o L4, da Universidade de Dresden; e o Amoeba, da Vrije Universiteir. A maioria das iniciativas nesta área está relacionada ao desenvolvimento de sistemas operacionais distribuídos. 4.8 Projeto do Sistema O projeto de um sistema operacional é bastante complexo e deve atender a diversos requisitos, algumas vezes conflitantes, como confiabilidade, portabilidade, manutenibilidade, flexibilidade e desempenho. O projeto do sistema ira depender muito da arqtiitetura cIo hardware a ser utilizado e do tipo de sistema que se deseja construir: batch, tempo compartilhado, monousuario ou multiusuário, tempo real etc. Os primeiros sistemas operacionais foram desenvolvidos integralmente em assembly e o código possuía cerca de um milhão de instruções (IBM OS/360). Com a evolução dos sistemas e o aumento do número de linhas de código para algo perto de 20 milhões (MULTICS), técnicas de programação modular foram incorporadas ao projeto, além de linguagens de alto nível, como PL/I e Algol. Nos sistemas operacionais atuais, o número de linhas de código pode chegar a mais de 40 milhões (Windows 2000), sendo grande parte do código escrita em linguagem C/C++, utilizando em alguns casos programação orientada a objetos. Urna tendência no projeto de sistemas operacionais modernos é a utilização de técnicas de orientação por objetos, o que leva para o projeto do núcleo do sistema todas as vantagens deste modelo de desenvolvimento de software. Existe uma série de vantagens na utilização de programação por objetos no projeto e na implementação de sistemas operacionais. A seguir, os principais beneficios são apresentados: • • • • melhoria ria organização das funções e recursos do sistema; redução no tempo de desenvolvimento; maior facilidade na manutenção e extensão do sistema; facilidade de implementação do modelo de computação distribuída. Além de facilitar o desenvolvimento e a manutenção do sistema, a utilização de linguagens de alto nível permite maior portabilidade, ou seja, que o sistema operacional seja facilmente alterado em outra arquitetura de hardware. Uma desvantagem do uso de linguagens de alto nível em relação à programação assembly é a perda de desempenho. Por isto, as partes criticas do sistema, corno os device drivers, o escalonador e as rotinas de tratamento de interrupções, são desenvolvidas em assembly. Um importante princípio no projeto de sistemas operacionais é a separação no projeto do sistema das políticas e dos mecanismos. Uma política define o que deve ser feito, enquanto um mecanismo define como implementar uma determinada política. 4.9 Exercícios 1. O que é o núcleo do sistema e quais são suas principais funções? 2. O que é uma system call e qual sua importância para a segurança do sistema? Como as system calls são utilizadas por um programa? 3. O que são instruções privilegiadas e não-privilegiadas? Qual a relação dessas instruções com os modos de acesso? 4. Quais das instruções a seguir devem ser executadas apenas em modo kernel? Desabilitar todas as interrupções, consultar a data e hora do sistema. alterar a data e hora do sistema, alterar informações residentes no núcleo do sistema, somar duas variáveis declaradas dentro do programa, realizar um desvio para uma instrução dentro do próprio programa e acessar diretamente posições no disco. 5. Explique como funciona a mudança de modos de acesso e dê um exemplo de corno um programa faz uso desse mecanismo. 6. Como o kernel do sistema operacional pode ser protegido pelo mecanismo de modos de acesso? 7. Compare as arquiteturas monolítica e de camadas. Quais as vantagens e desvantagens de cada arquitetura? 8. Quais as vantagens do modelo de máquina virtual? 9. Como funciona o modelo cliente—servidor na arquitetura microkernel? Quais são as vantagens e desvantagens dessa arquitetura? 10. Por que a utilização da programação orientada a objetos é um caminho natura] para o projeto de sistemas operacionais?