Baixe o app para aproveitar ainda mais
Prévia do material em texto
Sistemas Operacionais Implementação de Processos no MINIX 3 Parte II Prof. Sílvio Fernandes UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO DEPARTAMENTO DE CIÊNCIAS EXATAS E NATURAIS CURSO DE CIÊNCIA DA COMPUTAÇÃO Estruturas de dados de processos e arquivos de cabeçalho Vamos nos aprofundar em src/kernel Kernel.h torna possível garantir que todos os arquivos-fonte compartilhem um grande número de definições importantes, escrevendo-se a linha #include “kernel.h” Como a ordem de inclusão de arquivos de cabeçalho às vezes é importante, kernel.h também garante que essa ordenação seja feita corretamente e de um ver por todas 2 Estruturas de dados de processos e arquivos de cabeçalho A versão do núcleo de config.h reúne em um só lugar várias definições que provavelmente não precisarão de alterações As definições nas linhas 4717 a 4743 (v. 3.2.1 = 18 a 41) permitem a desativação seletiva de chamadas de núcleo Muitos arquivos de cabeçalho são amplamente usados, embora não o suficiente para serem incluídos em kernel.h 3 Estruturas de dados de processos e arquivos de cabeçalho Incluídos em kernel.h const.h: macros e constantes gerais usadas pelo núcleo proto.h: protótipo de todas as funções que devem ser conhecidas fora do arquivo em são definidas glo.h: variáveis globais do núcleo proc.h: define a tabela de processos do núcleo 4 Estruturas de dados de processos e arquivos de cabeçalho Cada entrada na tabela de processos é definida como uma estrutura de dados proc, contendo Campos para armazenamento dos registradores da CPU Ponteiro de pilha Estado Mapa de memória Limite da pilha Id de processo Informações de contabilização Temporizadores de alarmes Informação de mensagem do processo 5 Estruturas de dados de processos e arquivos de cabeçalho No MINIX 3, cada processo tem um ponteiro para uma estrutura priv em sua entrada na tabela de processos Essa estrutura define as origens e destinos de mensagens permitidos para o processo e muitos outros privilégios Cada entrada na tabela de processos fornece espaço para informações que podem ser necessárias para o núcleo P_max_priority: indica em qual fila de escalonamento o processo deve ser colocado quando estiver pronto para executar pela 1ª vez (ausente na v 3.2.1) 6 Estruturas de dados de processos e arquivos de cabeçalho Cada entrada na tabela de processos fornece espaço para informações que podem ser necessárias para o núcleo P_priority: começa com o valor de p_max_priority, mas como a prioridade pode ser reduzida, esse campo é usado para determinar a prioridade atual O tempo usado por cada processo é registrado nas 2 variáveis p_user_time e p_sys_time (linhas 5532 e 5533) P_nextready é usado para encadear processos nas filas do escalonador O método rendez-vouz de passagem de mensagem se torna possível graças ao espaço de armazenamento reservado nas linhas 5538 a 5540 (ausente na v 3.2.1) 7 Estruturas de dados de processos e arquivos de cabeçalho Cada entrada na tabela de processos fornece espaço para informações que podem ser necessárias para o núcleo O endereço do buffer de mensagens é armazenado em p_messbuf P_pending é um mapa de bits usado para monitorar os sinais que ainda não foram passados para o gerenciador de processos O último campo em uma entrada da tabela de processos é um array de caracteres (p_name) para conter o nome do processo 8 Estruturas de dados de processos e arquivos de cabeçalho Cada entrada na tabela de processos fornece espaço para informações que podem ser necessárias para o núcleo A macro proc_addr (linha 5577) (v.3.2.1 = linha 267) torna mais fácil monitorar qual entrada corresponde a qual processo, podemos escrever rp = proc_addr(n); A tabela de processos é um array de estruturas proc (linhas 5593) (v.3.2.1 = linha 276) 9 Estruturas de dados de processos e arquivos de cabeçalho A estrutura de privilégios de sistema, priv, está completamente definida em priv.h A estrutura de priv não faz parte da tabela de processos; em vez disso, cada entrada da tabela tem um ponteiro para uma instância dela Processos de sistema têm cópias privadas Processos de usuário apontam para a mesma cópia A organização de priv.h é semelhante a proc.h O último item de priv.h é um teste para garantir que NR_SYS_PROCS tenha sido definida com um valor maior que o número de processos presentes na imagem de boot (v. 3.2.1 = linha 92) 10 Estruturas de dados de processos e arquivos de cabeçalho A tecla F4 gera um dump de depuração que mostra algumas informações da tabela de privilégios 11 Estruturas de dados de processos e arquivos de cabeçalho No dump, as entradas de flags significam P: passível de preempção B: passível de cobrança S: sistema Os traps significam E: echo S: envio R: recepção B: ambos (sendrec) N: notificação 12 Estruturas de dados de processos e arquivos de cabeçalho No dump, o mapa de bits tem um bit para cada um dos processos de sistema NR_SYS_PROCS(32) permitidos A ordem corresponde ao campo id Todos os processos de usuário compartilham a id 0, que é a posição do bit mais à esquerda 13 Estruturas de dados de processos e arquivos de cabeçalho O arquivo protect.h (ausente v. 3.2.1) trata de detalhes da arquitetura dos processadores da Intel que suportam modo protegido O MINIX 3 tira proveito de 3 dos 4 níveis Partes centrais do núcleo que gerenciam trocas de contexto sempre são executadas com INTR_PRIVILEGE As tarefas executadas no nível TASK_PRIVILEGE podem acessar E/S, mas não usar instruções que modificam registradores especiais Os servidores e processos de usuário são executados no nível USER_PRIVILEGE 14 Estruturas de dados de processos e arquivos de cabeçalho O arquivo table.c (v. 3.2.1) contém apenas os programas que fazem parte da imagem do boot O arquivo table.c contém todas as estruturas de dados do núcleo, com declarações de variáveis com EXTERN na frente Entre as linhas 6075 e 6109 é definido o espaço de pilha necessário para os componentes do núcleo, e a quantidade total de espaço de pilha para tarefas é reservada como o array t_stack[TOT_STACK_SPACE] Define image (linha 6095) com os detalhes necessários para inicializar todos os processos carregados na imagem de boot Nessa definição qs se refere ao quantum atribuído a cada processo Se um novo processo precisa ser adicionado na imagem de boot, uma nova linha deverá ser fornecida na tabela 15 Inicialização do Sistema A 1ª parte do MINIX 3 a executar foi escrita em assembly e diferentes arquivos de código-fonte devem ser usados para o compilador de 16 ou 32 bits A versão de 32 bits do código de boot está em mpx386.s (ausente v. 3.2.1) A versão alternativa (16 bits) está em mpx88.s A seleção é feita atumaticamente em mpx.s 16 #include <minix/config.h> #if_WORD_SIZE == 2 #include “mpx88.s” #else #include “mpx386.s” #endif Inicialização do Sistema A inicialização do MINIX 3 envolve várias transferências de controle entre as rotinas em linguagem assembly presentes em mpx386.s e as rotinas em C presentes em start.c (ausente v. 3.2.1) e main.c Quando o processo de inicialização tiver carregado o SO na memória, o controle será transferido para o rótulo MINIX (em mpx386.s) Esse rótulo termina com um desvio (e não com uma chamada)para o ponto de entrada main do núcleo (main.c) Nesse ponto, mpx386.s está terminado 17 Inicialização do Sistema Praticamente, a 1ª coisa feita por cstart (em start.c) é configurar os mecanismos de proteção da CPU e as tabelas de interrupção, chamando prot_init Main (em main.c) completa a inicialização e depois inicia a execução normal do sistema A maior parte do código de main é dedicada à configuração da tabela de processos e da tabela de privilégios, para que, quando as 1as. tarefas e processos tiverem sua execução programada, seus mapas de memória, registradores e informações de privilégio estejam corretamente configurados 18 Inicialização do Sistema No Main.c Para cada tabela, toda entrada, esteja em uso ou não, precisa ser inicializada com um número de índice Uma nota sobre uma característica da linguagem C (linha 7153) (pproc_addr + NR_TASKS)[i] = rp; Também poderia ser escrito como pproc_addr[i + NR_TASKS] = rp; Cada tarefa precisa de seu próprio ponteiro de pilha privado, exceto KERNEL (também identificado como HARDWARE em alguns lugares) que nunca é considerado pronto e nunca é executado como um processo normal 19 Inicialização do Sistema No Main.c Uma vez que a tabela de processos foi inicializada para todas as tarefas, para os servidores e init, o sistema estará quase pronto para funcionar A variável bill_ptr identifica qual processo é cobrado pelo tempo do processador; ela precisa ter um valor inicial configurado e, claramente, IDLE é uma escolha apropriada Resta apenas o núcleo chamar announce para anunciar que está pronto e depois restart No núcleo do MINIX 3 a tarefa do main é realizada quando a inicialização é concluída; a chamada de restart inicia o primeiro processo enfileirado; o controle nunca retorna para main 20 Inicialização do Sistema No mpx386.s Há uma rotina _restart que não é uma função completa; trata-se de um ponto de entrada intermediário em uma função maior; causa uma troca de contexto para que o processo apontado por proc_ptr seja executado Finalmente, o gerenciador de processos e o sistema de arquivos executarão seu código de inicialização e suas partes da tabela de processos serão completadas Init criará um processo getty para cada terminal 21 Tratamento de Interrupção no MINIX Hardware de processamento de interrupção em um PC Intel de 32 bits 22 Tratamento de Interrupção no MINIX Os chips controladores de interrupção são programados durante a inicialização do sistema, quando main chama intr_init A programação determina o que é enviada para a CPU quando um sinal de interrupção é recebido em cada uma das linhas de entrada A identificação do tipo de interrupção (INTA) é colocada no barramento através de 8 bits que são usados para indexar uma tabela de até 256 elementos A tabela do MINIX 3 tem 56 elementos Onde 35 são realmente usados 23 Tratamento de Interrupção no MINIX O modos de resposta às interrupções utilizado pelo MINIX 3, em cada um dos descritores de interrupção, apontam para o segmento de memória onde reside o código executável da rotina de serviço e o endereço inicial da rotina dentro dele. Se a CPU recebe uma interrupção enquanto está executando um processo ela configura uma nova pilha para uso durante o serviço de interrupção A localização dessa pilha é determinada por uma entrada em um segmento de estado de tarefa (Task State Segment – TSS) Existe apenas uma estrutura dessa para o sistema inteiro 24 Tratamento de Interrupção no MINIX No arquivo mpx386.s examinaremos a minúscula parte do núcleo do MINIX 3 que realmente vê as interrupções de HW O código-fonte em cada ponto de entrada, _hwint00 a _hwint07, parecem com a chamada hwint_master E os pontos de entrada _hwint08 a _hwint15 são similares à chamadas para hwint_slave Cada ponto de entrada passa um parâmetro (irq) na chamada indicando qual dispositivo precisa de serviço 25 Tratamento de Interrupção no MINIX No arquivo mpx386.s As 2 tabelas declaradas em glo.h são usadas _Irq_handlers contém as informações de gancho (hook) o que inclui os endereços das rotinas de tratamento (Re)configura um flag no array _irq_actids para indicar se a tentativa de atender a interrupção foi bem-sucedida (valor diferente de zero mostra que o tratamento não está terminado) 26 Tratamento de Interrupção no MINIX No MINIX 3 as interrupções não são ativadas enquanto o código do núcleo está em execução Mas isso não acontece com exceções, as quais não devem acontecer enquanto o núcleo estiver sendo executado, essa situação se denomina de pânico no núcleo (kernel panic) Quando todas as rotinas do núcleo envolvidas na resposta a uma exceção tiverem terminado, _restart finalmente será executada 27 Tratamento de Interrupção no MINIX Em resposta a uma exceção, quase certamente será verdade que será escalonado um processo diferente do que foi interrompido 28 Tratamento de Interrupção no MINIX 29 Tratamento de Interrupção no MINIX Uma exceção é causada por várias condições de erro internas da CPU As exceções nem sempre são ruins Elas podem ser utilizadas para estimular o SO a fornecer um serviço, como providenciar mais memória para um processo ou fazer swapping de uma página de memória, embora tais serviços não sejam implementados no MINIX 3 Elas também podem ser causadas por erros de programação 30 Tratamento de Interrupção no MINIX As exceções são tratadas pelo mesmo mecanismo das interrupções, usando descritores na tabela de descritores de interrupção Essas entradas na tabela apontam para os 16 pontos de entrada de rotina de tratamento de exceção, começando com _divide_error e terminando com _copr_error (final de mpx386.s) Todos desviam para exception ou para errexception dependendo de a condição colocar um código de erro na pilha ou não 31 Referências TANENBAUM, Andrew S.; WOODHULL, Albert S. Sistemas Operacionais: Projeto e Implementação. 3ª Ed., Prentice Hall, 2008. 32
Compartilhar