Baixe o app para aproveitar ainda mais
Prévia do material em texto
1 Resumo das aulas de Projeto Lógico de Computadores NP1 Sumário 1. Nível ISA ................................................................................................................................ 2 1.1. Propriedades do nível ISA ............................................................................................. 2 1.2. Instruções ...................................................................................................................... 2 1.3. Formato de Instruções .................................................................................................. 3 1.4. Critérios para a Determinação do Formato das Instruções .......................................... 3 1.5. Expansão dos Códigos de Operação ............................................................................. 4 1.6. Endereçamento ............................................................................................................. 4 1.6.1. Endereçamento Imediato ...................................................................................... 4 1.7. Fluxo de Controle .......................................................................................................... 5 1.7.1. Procedimentos de Fluxo de Controle .................................................................... 6 2. Interruptores ........................................................................................................................ 7 2.1. Ações do hardware ....................................................................................................... 7 2.2. Ações do software ......................................................................................................... 7 3. Nível de Sistema Operacional .............................................................................................. 8 3.1. Memória Virutal ............................................................................................................ 8 3.2. Paginação ...................................................................................................................... 8 3.3. Fragmentação Interna ................................................................................................... 9 3.4. Segmentação ................................................................................................................. 9 3.4.1. Comparação entre Paginação e Segmentação .................................................... 10 3.5. Fragmentação Externa ................................................................................................ 10 3.6. Criação de Processos ................................................................................................... 11 4. Memória Virtual no Pentium II .......................................................................................... 12 4.1. Introdução – Paginação por Demanda ........................................................................ 12 5. Exemplos de Sistemas Operacionais .................................................................................. 14 1. Unix ................................................................................................................................. 14 2. Windows NT .................................................................................................................... 15 2 1. Nível ISA Primeiramente deve fazer um esclarecido entre nível ISA, que é o software, e Barramento ISA, que simboliza o hardware do computador. Também denominado como nível de arquitetura do conjunto das instruções, o nível ISA (Instruction Set Architecture) é responsável principalmente pela compatibilidade de máquinas e sistemas antigos com os novos. Ao surgir uma nova máquina no mercado, a principal preocupação é quanto à compatibilidade dessa nova máquina com as suas antecessoras, bem como seus programas e sistemas operacionais; por isso, usa-se o nível ISA foi elaborado para servir como um intermediário dos níveis de SO e Linguagem de Montagem (elaborada para os programas) aos níveis da Micro-arquitetura e Lógico- Digital, aonde se localizam principalmente o hardware. Esse nível começa sempre no início de um projeto envolvendo criação de novas máquinas. Sempre que ele é desenvolvido, o nível ISA é divulgado para os fornecedores de software, para que tenham tempo de desenvolver compiladores que rodam nas novas máquinas desse nível. As características de um bom projeto de nível ISA são: definir um conjunto de instruções que possa ser implementado tanto nas tecnologias atuais quanto futuras e fornecer uma interface eficiente com o compilador e com o hardware. 1.1. Propriedades do nível ISA Para que esse nível cumpra seu objetivo, ele define o aspecto da máquina para um programador da linguagem de máquina, ou seja, as suas instruções são aquelas para as quais o compilador deve gerar código. Para fazer com que o compilador gere código para o nível ISA, o projetista desse compilador deve conhecer muito bem o modelo de memória da máquina, quais registradores estão implementados, quais os tipos de dados e de instruções disponíveis e assim por diante, sendo o conjunto de todas essas informações é o que define o nível ISA. 1.2. Instruções A principal característica desse nível é o seu conjunto de instruções de máquina. Essas instruções controlam tudo o que uma máquina pode fazer. Do conjunto de instruções de uma máquina sempre fazem parte instruções como LOAD e STORE, por exemplo, para permitir o movimento de dados entre a memória e os registradores. 3 1.3. Formato de Instruções Um programa é constituído de uma sequência de instruções, cada uma especificando alguma ação em particular. As instruções contêm, obrigatoriamente, “códigos de operação” que irão gerar a ação desejada. Muitas instruções contêm, ou especificam, o endereço ou dado a ser usado pela instrução. Por exemplo: uma instrução que compara duas informações para checar se são iguais deve especificar quais caracteres devem ser comparados. Inicialmente, o formato das instruções constitui-se no código de operação, mas, conforme as instruções necessitam conter endereços dos dados a serem utilizados por eles, eles adequam o espaço necessário para alocar esse endereço, diminuindo o espaço para o código de operação, otimizando-o. Esse formato é alterado em toda a vez que é requerido um espaço de endereçamento, que será fixo, e adequando o espaço do código de operação, sem repetir. Portanto, quanto maior a complexidade das instruções (ou seja, quanto maior a quantidade de endereços), menor será o tamanho do código de operação. Em algumas máquinas todas as instruções têm o mesmo tamanho, e em outras pode haver instruções de diversos tamanhos. As instruções de uma máquina podem ser menores, do mesmo tamanho ou maiores que o tamanho da palavra da máquina. O fato de todas as instruções terem o mesmo tamanho (mesmo número de bits) simplifica muito o projeto do hardware. 1.4. Critérios para a Determinação do Formato das Instruções O formato das instruções não é realizado de forma deliberada; existem alguns critérios para a sua determinação, compostos por: • Instruções curtas são melhores que as longas, por serem menos complexas e ocuparem menos memória; • Cada memória tem uma determinada taxa de transferência (medida em bps – bits por segundo), a qual é maior para instruções mais curtas, o que aumenta a velocidade de processamento; • É desejável que o comprimento da palavra seja um múltiplo inteiro do comprimento das instruções; 4 1.5. Expansão dos Códigos de Operação A técnica da expansão dos códigos de operação é utilizada para permitir que todas as instruções de um conjunto possam manter o mesmo tamanho. Para instruções simples utiliza-se códigos de operação mais longos, poupando os códigosde operação mais curtos para as instruções mais complexas e que, por isso, necessitam de mais dados no corpo da instrução. Nessa técnica, usa-se como parâmetro o tamanho em bits do código de operação, aonde é atribuído um conjunto N de instruções (sendo de 0 a N-1) em cada grupo; ao final da execução desse grupo, para executar o próximo grupo, é atribuído 1 ao código final do grupo anterior, no qual recomeça a contagem binária a partir do código final anterior somado aos bits do tamanho do novo grupo. Ex.: 1º grupo com 15 instruções de código de operação 4 bits = variação de 0000 a 1110 no código; 2º grupo com 14 instruções de código de operação 8 bits: 1110 (código final do grupo anterior) + 1 = 1111 (novo código inicial) = variação de 1111 0000 a 1111 1101; e assim por diante. OBS.: Para realizar essa operação de forma mais rápida, ou com um grande número de instruções, transforme o número do termo em que está a variação (ex.:I4, lembrando sempre que varia de 0 a N-1 os termos) de decimal para binário, e depois adiciona-o ao valor do primeiro termo, ou seja, o código inicial dessa variação: ex.: 4(10) = 100(2) e, se o valor do primeiro termo for 000, ele será 100 neste quarto termo. 1.6. Endereçamento Uma instrução pode ter mais de um endereço associado a ela. As formas de se endereçar uma determinada posição de memória, ou determinado registrador, são diversas, de acordo com a natureza da operação a ser executada. 1.6.1. Endereçamento Imediato A maneira mais simples de uma instrução especificar um operando é contê-lo no campo de endereçamento ao invés de endereça-lo. Este tipo de operando é denominado operando imediato porque é trazido da memória junto com a instrução e está imediatamente disponível para execução. Essa forma de endereçamento portanto não usa nenhuma outra referência para buscar o operando. Diferentemente dessa especificação, há também: • Endereçamento direto: ocorre quando a instrução contém o endereço de memória onde está o operando necessário • Endereçamento do Registrador: ocorre quando a instrução contém o endereço do registrador onde está o operando necessário 5 • Endereçamento indireto: ocorre quando a instrução contem o endereço de uma posição de memória a qual contem, por sua vez, o endereço do operando necessário • Endereçamento Indireto Múltiplo: ocorre quando a instrução do 1º endereço de uma posição de memória a qual contem outros endereços, até que o endereço do operando desejado seja alcançado. • Endereçamento por Indexação: o endereço do operando é a soma da constante mais o conteúdo do registrador indicado. Há também o endereçamento por base-deslocamento, aonde o endereço do operando é a soma da base (que está num registrador) mais o deslocamento. Este caso e o anterior podem coincidir se o deslocamento tenha bits o suficiente para endereçar toda a memória, será designado de endereçamento por Indexação, ou, caso contrário, será designado por Base-Deslocamento. Por fim, uma outra forma de endereçamento é endereçamento por pilha, que contém o endereço do topo da pilha, e é atualizado a cada entrada ou saída de informação na pilha. 1.7. Fluxo de Controle Entende-se por fluxo de controle a sequência na qual instruções são dinamicamente executadas no decorrer de um programa. Em geral, na ausência de desvios e de chamadas a procedimentos, as instruções vão sendo executadas sucessivamente, a partir de endereços consecutivos na memória. As instruções de chamada a procedimento alteram esse fluxo, fazendo com que o procedimento corrente pare de ser executado, começando a execução do novo procedimento. As co-rotinas são estruturas parecidas com os procedimentos e também causam o mesmo tipo de alteração no fluxo de controle. As co-rotinas são úteis na implementação de paralelismo de outros processos. As interrupções e os traps também alteram o fluxo de controle, quando determinadas condições especiais ocorrem. A execução da maioria das instruções de uma máquina não altera o fluxo de controle. Em geral, após a execução de uma instrução, o processador vai à memória para buscar a instrução armazenada no endereço seguinte àquela que acabou de ser executada. A ordem dinâmica na qual um processador executa suas instruções é a mesma em que elas aparecem na listagem do programa. Se um programa contiver desvios, essa relação simples entre a ordem em que a instrução aparece na memória e a ordem de sua execução desaparece. Quando existem desvios, o valor armazenado no registrador PC não é mais uma função linear no tempo. Como resultado disso, torna-se difícil visualizar a sequência de execução das instruções a partir da listagem do programa. 6 1.7.1. Procedimentos de Fluxo de Controle O procedimento, ou sub-rotina, é a técnica mais importante para a estruturação de programas. De um lado, uma chamada a procedimento altera o fluxo de controle exatamente do mesmo modo que um desvio, mas o procedimento, ao contrário do desvio, quando termina sua tarefa retorna o controle para o comando ou instrução seguinte à instrução de chamada. Uma sub-rotina é um grupo de instruções que executa alguma tarefa, e pode ser chamada em vários pontos do programa. Ao final da sub- rotina há uma instrução de retorno ao programa chamador. 1.7.1.1. Co-Rotinas Os dois procedimentos podem considerar um ao outro como procedimento chamador e chamado. Quando uma co-rotina é retomada, a execução começa no comando suspenso anteriormente, e não no início. 1.7.1.2. Traps Uma trap é uma chamada a procedimento automática, iniciada sempre que ocorrer alguma condição específica causada pela execução de um programa. Por exemplo: divisão por zero, violação de proteção, código de operação inválido, tentativa de acessar periférico de E/S que não existe, etc. O trap é disparado para evitar que uma anormalidade cause danos ao processamento. Para isso, ele detecta o problema para o qual foi planejado e alerta a ocorrência. O trap não tem, contudo, recursos para uma eventual recuperação do problema e nem para reiniciar o processamento. 1.7.1.3. Interrupções As interrupções são modificações no fluxo de controle de um programa causadas por um evento externo ao processamento do programa, usualmente relacionados a operações de E/S. Por exemplo, um programa pode instruir o disco para iniciar uma transferência de informações, e programá-lo de maneira que ele gere uma interrupção tão logo a transferência se conclua. Da mesma forma que ocorre com as traps, as interrupções também param o processamento do programa atual e transferem o controle para uma rotina de tratamento de interrupção, que executa ações apropriadas. Quando essa rotina termina sua execução, o controle retorna ao programa que teve seu processamento interrompido, o qual reinicia exatamente do ponto em que havia parado. Por fim, as interrupções têm como funções principais disparar programas interruptores e controlar as prioridades dentro da máquina. 1.7.1.4. Traps X Interrupções A diferença entre um trap e uma interrupção é o fato de que os traps são síncronos com o programa, enquanto que as interrupções são assíncronas. Se um programa for processado milhões de vezes, com as mesmas entradas, os traps vão ocorrer nos mesmos instantes relativos, a cada nova execução do programa. A ocorrência das interrupções irá variar a cada processamento, dependendo das ações dos dispositivos de E/S a cada instante. 7 2. Interruptores 2.1. Ações do hardware 1. O controlador do dispositivo ativa uma linha de interrupção no barramento do sistema para iniciar a sequência de interrupção. 2. Tão logo esteja pronto para tratar a interrupção, o processador ativa no barramento um sinal de reconhecimento da interrupção. 3. Quando o controlador do dispositivo enxerga o reconhecimento do sinal de interrupção, coloca um pequenovalor inteiro nas linhas de dados, para identificação dele próprio. Esse número é conhecido como valor de interrupção. 4. O processador remove o vetor de interrupção do barramento e salva seu valor temporariamente. 5. Em seguida, o procedimento coloca na pilha o conteúdo do registrador Contador de Programa e do registrador contendo a PSW (Program Status Word). 6. Depois disso o processador localiza um novo Contador de Programa com a ajuda do vetor de interrupção que funciona como um índice para uma tabela situada na parte baixa da memória. Muitas vezes a PSW é carregada e modificada (como no caso de ser necessário desabilitar outras interrupções por algum tempo). 2.2. Ações do software 1. A primeira coisa que a rotina de treinamento de interrupção deve fazer é salvar o conteúdo de todos os registradores a fim de possibilitar que eles sejam restaurados mais tarde. Esses valores podem ser salvos na pilha ou em uma tabela do sistema. 2. Cada vetor de interrupção é compartilhado por todos os dispositivos de um mesmo tipo, de maneira que nesse momento ainda não se conhece quais terminais causou a interrupção. O número do terminal será conhecido a partir da leitura de um registrador do dispositivo. 3. Qualquer outra informação sobre interrupção, como códigos de estado, pode ser obtida a partir desse momento. 4. Caso tenha ocorrido algum erro de E/S, ele poderá ser tratado agora. 5. Se necessário, é gerado um código especial para informar ao dispositivo ou ao controlador do dispositivo que uma interrupção está sendo processada. 6. Todos os valores originais dos registradores são restaurados. 7. É executada a instrução RETURN FROM INTERRUPT, colocando o processador de novo no modo e no estado que ele tinha imediatamente antes da ocorrência da interrupção. O processador continua o processamento do programa como se nada tivesse acontecido. 8 3. Nível de Sistema Operacional Um Sistema Operacional, ou SO, é um programa que, do ponto de vista do programador, adiciona um conjunto de novas instruções e de funcionalidades, além das suportadas no nível ISA. Normalmente um SO é implementado por software, mas nada impede que ele o seja por hardware. O conjunto de instruções do nível SO é aquele que está disponível para os programadores de aplicações. Uma Chamada de Sistema ativa um determinado serviço prestado pelo SO ao nível da aplicação. Um exemplo de uma chamada de serviço é o comando de leitura de um dado num arquivo. 3.1. Memória Virutal Em tempos passados as máquinas tinham memórias pequenas e caras. A busca do programador não era pelo melhor algoritmo, mas sim pelo algoritmo que coubesse na memória. Nessa época surgiu a técnica dos overlays, os quais eram totalmente controlados pelo programador. Os overlays eram pedaços de um programa que ficavam em disco, e eram chamados para a memória no momento de serem executados, sendo o uso desse método era muito trabalhosa para o programador. Surgiu, então, um método para processá-los automaticamente, ou seja, sem que o programador precisasse saber da sua existência. Este método ficou conhecido como Paginação. A memória virtual opera com base na técnica da paginação a qual, por sua vez, vem do conceito de espaço de endereçamento. Vamos definir espaço de endereçamento como sendo o número de palavras endereçáveis. Se tivermos 16 bits para endereçamento, teremos 2^16 = 65536 endereços possíveis, portanto o espaço de endereçamento compreende os endereços de 0 a 65535. Para uma memória de 4kB, aonde, se cada palavra for do tamanho de um byte, teremos uma memória de 4096 palavras. 3.2. Paginação Esta técnica de overlay automático é denominada, portanto, como paginação, e o conjunto de endereços lidos do disco é chamado de página. A memória física pode ser, então, menor que o espaço de endereçamento. Retomando o exemplo anterior, as páginas serão blocos de 4kB que serão carregados na memória na medida da necessidade. A memória principal contém sempre 4kB de informação, mas não necessariamente os primeiros 4kB do espaço de endereçamento, mas qualquer bloco de 4kB. 9 A paginação é, na prática, mais complexa, uma vez que uma determinada memória física pode abrigar mais de um bloco de dados. O controlador deste processo de organização de blocos ocorre através de uma Tabela de Paginação, que contém como colunas: número da página, indicador de paginação, endereço no disco e número de frame (que é um espaço na memória destinado ao encaixe de uma página, aonde um frame pode abranger um conjunto de endereços). Para o indicador de paginação, há apenas duas opções: 0, que simboliza a não-alocação da página na memória, ou 1, que simboliza sua alocação na memória. 3.3. Fragmentação Interna Se por sorte o programa do usuário e seus dados couberem exatamente em um número inteiro de páginas, não haverá desperdício de espaço de memória quando essas informações estiverem armazenadas na memória principal. Por outro lado, se tais informações não puderem ser acomodadas em um número inteiro de páginas, haverá espaço disponível (não utilizado) na última página. Por exemplo, se um programa e seus respectivos dados ocuparem 26000 bytes em uma máquina com 4096 bytes por página (4kB), as seis primeiras páginas estarão cheias, e a última conterá apenas 1424 bytes. Esse tipo de problema é denominado fragmentação. 3.4. Segmentação O sistema de memória virtual visto até agora é unidimensional, pois os endereços variam consecutivamente de 0 até um endereço máximo. Na solução de alguns problemas é conveniente a existência de mais de um espaço de armazenamento. Por exemplo, um compilador gera muitas tabelas que precisam ser construídas na medida em que o processo de compilação evolui. Destas tabelas pode-se citar: a tabela de símbolos, contendo o nome e os atributos das variáveis; a tabela com o código-fonte; uma tabela contendo todas as constantes; uma tabela analítica, contendo a análise sintática do programa; etc. Estas tabelas vão sendo preenchidas na medida em que o processo de combinação avança. Se o espaço de endereçamento for único, as faixas destinadas às diversas tabelas podem estourar sua capacidade. A solução é segmentar o espaço de endereçamento em vários espaços independentes entre si. Desta forma, os espaços podem crescer, ou diminuir, na medida da necessidade. Além disso, é possível atribuir níveis diferentes de segurança para cada espaço. Portanto, segmentação é um processo da separação, via configuração manual, dos processos de compilação, evitando assim a parada imediata do compilador por “estouro” de informações em um dos processos. 10 3.4.1. Comparação entre Paginação e Segmentação • “O programador precisa saber que o sistema usa essa técnica?” No processo de paginação não é necessário, enquanto que na segmentação é necessário que saiba. • “Quantos espaços lineares de endereços existem?” Na paginação há apenas um espaço (Tabela de Paginação), enquanto que na segmentação há muitos espaços (Tabela de símbolos, tabela do código-fonte, etc.) • “O espaço de endereçamento virtual pode exceder o tamanho da memória?” Tanto na paginação quanto na segmentação isso pode acontecer. • “As tabelas de tamanho variável podem ser tratadas com facilidade?” Na paginação infelizmente isso não ocorre, porém na segmentação esse tratamento é mais fácil. • “Por que esta técnica foi inventada?” Na paginação esta técnica foi feita para simular memórias maiores que a primária, enquanto que na segmentação foi para permitir o uso de vários espaços de endereçamento. A segmentação pode ser implementada de duas maneiras: por swapping e por paginação. No swapping um conjunto de segmentos deve estar na memória principal em um certo instante. Se ocorrer uma referência a um segmento que não está na memória principal, este segmentodeve ser trazido do disco para a memória. Se não houver espaço para ele na memória, um ou mais segmentos devem ser retirados da memória e escritos de volta no disco. Em certo sentido, a segmentação implementada por swapping não é muito diferente da paginação por demanda: os segmentos vão e vem do disco para a memória principal, e vice-e-versa, na medida em que são necessários. Há, contudo, uma diferença essencial entre os dois métodos: as páginas têm tamanho fixo, e os segmentos não têm. 3.5. Fragmentação Externa A fragmentação externa ocorre entre segmentos, e não dentro deles. A sucessiva troca de segmentos numa memória principal cria intervalos ociosos que representam um desperdício deste recurso. Este problema é tratado através da compactação dos intervalos ociosos. A compactação consome tempo de máquina para executar sua tarefa e não pode ser executada a cada movimentação de segmentos, mas somente a determinados intervalos de tempo. Para alocar área para um arquivo em disco, o SO utiliza, habitualmente, dois métodos: A Lista Livre, uma lista no qual ocorre a contagem de trilhas livres, selecionando inicialmente uma trilha de um setor e contando no sentido horário até achar uma trilha ocupada, e O Mapa de Bits. 11 3.6. Criação de Processos Quando um programa roda, ele o faz como parte de algum processo. Os sistemas operacionais modernos permitem a criação, e destruição, dinâmica de processos. Há duas possibilidades: • O processo-pai cria, e mantém controle, sobre o processo-filho (total ou parcial). a. Há necessidade de instruções virtuais para permitir que o processo-pai possa parar e retomar a execução de um processo-filho. b. Idem, para examiná-lo e termina-lo. • O processo-pai cria o processo-filho e este torna-se um processo independente. 12 4. Memória Virtual no Pentium II 4.1. Introdução – Paginação por Demanda É possível iniciar a executar um programa em uma máquina com memória virtual sem que nenhuma de suas páginas esteja na memória principal. A tabela de páginas desse programa indica que todas as suas páginas estão na memória secundária. Quando o processador tentar buscar a primeira das instruções do programa, haverá a geração de uma falta de página, que fará com que a página contendo a primeira instrução seja carregada na memória principal. Então a primeira instrução pode ser executada. Se essa instrução referenciar dois endereços, e esses endereços estiverem em páginas diferentes daquela onde está a instrução, serão geradas mais duas faltas das páginas, e mais duas páginas serão trazidas do disco, antes que a execução da instrução tenha terminado. A próxima instrução poderá causar ainda mais faltas de página, e assim por diante. Este método de operação de um sistema de memória virtual é conhecido como paginação por demanda. Nesta situação, as páginas são trazidas para a memória principal em função de requisições explícitas para cada uma delas, e não antecipadamente. A questão da adequação da utilização da paginação por demanda só é relevante na fase inicial da execução de um programa. Na medida em que o programa já estiver rodando há algum tempo, as páginas necessárias à sua execução já deverão ter sido coletadas da memória secundária estando, portanto, residentes na memória principal. O Pentium II tem um sistema muto sofisticado de memória virtual que suporta: a paginação por demanda, a segmentação pura e a segmentação com paginação. O coração da memória virtual está situado em duas tabelas: a LDT (Local Descriptor Table – Tabela de Descritores Locais) e a GDT (Global Descriptor Table – Tabela de Descritores Globais). Cada programa tem sua própria LDT, mas só existe uma única GDT, compartilhada por todos os programas que rodam no processador. A LDT descreve os segmentos locais a cada um dos programas, incluindo seu código, seus dados, sua pilha, e assim por diante, enquanto que a GDT descreve os segmentos do sistema, inclusive os segmentos do próprio sistema operacional. Para acessar um segmento, um programa precisa primeiro carregar um seletor para um dos registradores de segmento. Durante a execução do programa, um registrador guarda o seletor do segmento de código, e outro registrador guarda o seletor do segmento de dados, e assim por diante. Um dos bits do seletor informa se o segmento é local ou é global. Treze bits especificam o número da entrada na LDT ou na GDT. Dois bits estão ligados à proteção. Cada programa ativo tem um diretório de páginas composto de 1024 entradas de 32 bits cada. Esse diretório localiza-se em um endereço apontado por um registrador global. Cada entrada nesse diretório aponta para uma tabela de páginas, que também 13 contém 1024 entradas de 32 bits cada. As entradas da tabela de páginas apontam para molduras de páginas. No quesito de proteção, o Pentium II suporta 4 níveis de proteção, sendo o nível 0 o mais privilegiado e o nível 3 o menos privilegiado: nível 0 é aonde fica as chamadas de sistema, enquanto que o nível 2 são as bibliotecas compartilhadas e o nível 3 os programas de usuário. A cada instante, o programa que estiver rodando está em um determinado nível, identificado por um campo de 2 bits de sua PSW (Program Status Word – Palavra de Estado do Programa). 14 5. Exemplos de Sistemas Operacionais 1. Unix O Unix foi desenvolvido no início dos anos 1970 na Bell Labs por Ken Thompson. Esse sistema foi escrito em C, linguagem projetada e desenvolvida por Dennis Ritchie. A Universidade de Berkeley, na Califórnia, adquiriu o código-fonte original do Unix e os seus cientistas aprimoraram-no substancialmente. Com isso, foram criadas no UNIX as seguintes funcionalidades: portabilidade, memória virtual paginada, extensão de arquivos com até 255 caracteres e criação do protocolo TCP/IP. A estrutura desse SO é caracterizada pelo modo usuário, aonde se encontram o shell e programas de usuários, que utiliza uma interface para chamadas de sistema para ter acesso ao modo kernel, aonde se localizam componentes como sistema de arquivo, gerência de processos e drives de dispositivo. Os drives de dispositivo fazem a interface do sistema de arquivos com o harware da máquina. Originalmente, cada driver de dispositivo era programado como sendo uma entidade independente, separada de todas as outras. Esse esquema levava a muito esforço duplicado, pois os drives precisavam tratar com o fluxo de controle do programa, precisavam tratar com o fluxo de controle do programa, precisam tratar erros, prioridades, separar os dados do controle, e assim por diante. No sistema de arquivo, ocorre a gerência os nomes dos arquivos e de diretórios, a alocação de blocos de disco, a proteção, etc. A cache de blocos faz parte do sistema de arquivos, com a função de armazenar os blocos lidos mais recentemente do disco, para o caso deles serem necessários novamente em breve. A outra parte do kernel do UNIX é responsável pela gerência dos processos. Entre suas funções, ela trata da comunicação entre processos (IPC – Inter Process Communication), que permite que os processos se comuniquem uns com os outros, para estabelecer uma sincronização de suas execuções. A gerência da memória também é implementada na parte relativa à gerência de processos. A maioria dos sistemas UNIX suporta memória virtual com base na paginação por demanda, às vezes com algumas características extras, como a capacidade de permitir que vários processos compartilhem a mesma região do espaço de endereçamento. As primeiras versões do UNIX tinham interface com o usuário totalmente baseada em texto. Essa interface era tratada por um programa conhecido como shell, que rodava no nível do usuário, cuja comunicação com o usuário era feitapor intermédio de comandos de linha. O shell não fazia parte do kernel, sendo, portanto, muito fácil programar em shell e incorporá-lo ao UNIX. 15 2. Windows NT Com o passar dos anos, o MS-DOS continuou a ganhar novas características, mas nunca deixou de ser um sistema operacional orientado a comandos de linha. A Microsoft, inspirada no sucesso do sistema Macintosh da Apple, decidiu dar ao MS-DOS uma interface gráfica, à qual deu o nome de Windows. As primeiras três versões dele, inclusive a versão Windows 3.x, não eram SOs na acepção da palavra, mas simplesmente interfaces gráficas com o usuário no topo do MS-DOS, que ainda era o responsável pelo controle da máquina. Todos os programas rodavam no mesmo espaço de endereçamento e um problema ocorrido em um deles poderia derrubar todo o sistema. O Windows NT trabalhava com 32 bits, e não sofreu influência de qualquer outro sistema. Por esta razão, a sigla NT significa New Technology. O NT era vendido em duas versões: servidor (server) e estação de trabalho (workstation), sendo elas duas geradas a partir do mesmo código-fonte. A versão servidor era voltada para máquinas que rodavam o sistema de arquivos de redes locais e que atuavam como servidores de impressão, tendo um gerenciamento mais elaborado do que aquele exercido pela versão estação de trabalho. O NT suportava multiprogramação, permitindo com que vários usuários trabalhassem simultaneamente. Com relação à sua estrtura, ela é dividida em três partes: modo usuário, executivo e modo kernel. No modo kernel, há uma parte chamada de nível de abstração de hardware, que tem a função de apresentar ao resto do SO dispositivos abstratos de hardware, livres das características específicas de cada módulo existentes no hardware real, como por exemplo: caches implementadas fora do chip, temporizadores, barramentos de E/S, controladores de interrupções, etc. Isto facilitava a portabilidade do NT para diferentes máquinas. O microkernel e os drives de dispositivo, também no mesmo modo que o anterior, têm acesso direto ao hardware. O microkernel suportava objetos básicos do kernel, as interrupções, os traps, o tratamento de exceções, o escalonamento de processos e a sincronização entre processos, a sincronização de vários processadores e o gerenciamento do tempo do processador. O propósito dele era tornar o resto do SO completamente independente do hardware, propiciando, portanto, a portabilidade independentemente da arquitetura do computador. O código do microkernel permanecia residente na memória, não podendo sofrer preempção, ou seja, este código não podia sair da memória principal. Com relação aos drives de dispositivos, cada driver controlava um ou mais dispositivos de E/S, mas um driver podia realizar tarefas que não estejam diretamente relacionadas com um dispositivo específico, como criptografar um stream de dados ou prover acesso a estruturas de dados do kernel. Havia a necessidade de tomar cuidado com os drives, pois como as pessoas podiam instalar novos drives, e como eles tinham acesso ao kernel, havia a possiblidade de corromper a estrutura do kernel. No modo executivo, este módulo era totalmente independente da arquitetura e, portanto, podia ser portado para outras máquinas. Esse modo era composto por três 16 níveis com várias funções em cada um deles: sistema de arquivos, que suportava o uso dos arquivos e dos diretórios; gerente de objetos, que tratava os objetos conhecidos do kernel: processos, threads (processos simples que rodam dentro de um único espaço de endereçamento), arquivos, diretórios, semáforos, temporizadores, etc.; gerente de E/S, que provia um ambiente para possibilitar o controle dos dispositivos de E/S; gerente da cache, que mantinha na memória principal os blocos do disco mais recentemente usados para acelerar o acesso a eles no caso deles serem utilizados novamente; gerente da memória virtual, que implementava a arquitetura da memória com base na paginação por demanda; gerente de processos e de threads, que tratava dos processos e das threads, incluindo sua criação e sua destruição; e, por fim, os serviços do sistema, cuja função era implementar uma interface para o Executivo, aceitando as chamadas de sistema do NT e chamando as outras partes do Executivo para executá-las.
Compartilhar