Sistemas Operacionais II Weig Tatiele Ludmila Subsistemas, DLLs e serviços do modo usuário Windows Vista consiste em componentes no modo nucleo e componentes no modo usuario. Componentes de modo usuário Existem três tipos importantes de componentes para o Windows de maneira singular: 1. Subsistemas de ambiente 2. DLLs 3. Processos de serviço Subsistemas, DLLs e serviços do modo usuário No projeto original do NT, os subsistemas eram vistos como uma maneira de dar suporte a varias personalidades de sistemas operacionais com o mesmo software de fundamento sendo executando no modo núcleo. Subsistemas, DLLs e serviços do modo usuário Talvez essa tenha sido uma tentativa de evitar que os sistemas operacionais competissem pela mesma plataforma, como o VMS e o Berkeley Unix fizeram com o VAX da DEC. Talvez ninguém na Microsoft soubesse que o OS/2 teria sucesso como uma interface de programação, e então estavam protegendo suas apostas. Em qualquer dos casos, o OS/2 tornou se irrelevante e um retardatário, e a API do Win32, projetada para ser compartilhada com o Windows 95 virou dominante. Subsistemas, DLLs e serviços do modo usuário Um segundo aspecto chave do projeto do modo de usuário do Windows é a biblioteca de ligação dinâmica (DDL) que é código sendo ligado a programas executáveis em tempo real em vez de tempo de compilação. Subsistemas, DLLs e serviços do modo usuário As bibliotecas compartilhadas não são um conceito novo e a maior parte dos sistemas operacionais modernos as utiliza. No Windows quase todas as bibliotecas são DLLs, desde a biblioteca de sistema ntdll.dll que é carregado em todo processo, até as bibliotecas de altos níveis de funções comuns que se destinam a permitir a reutilização de código por desenvolvedores de aplicações. Subsistemas, DLLs e serviços do modo usuário As DLLs aumentam a eficiência do sistema permitindo que código comum seja compartilhado entre processos reduzem os tempos de carregamento dos programas do disco mantendo na memória os códigos usados com freqüência e aumentam a capacidade de manutenção do sistema, permitindo que o código de bibliotecas do sistema operacional seja atualizado sem ter de recompilar ou religar todos os programas que o utilizem. Subsistemas, DLLs e serviços do modo usuário As DLLs são usadas para mais do que apenas compartilhar códigos comuns. Elas habilitam um modelo de hospedagem para estender as aplicações. O internet Explorer pode descarregar e se ligar a DLLS chamadas controles ActiveX. Na outra ponta da internet, servidores da Web também carregam código dinâmico para produzir uma experiência Web melhor para as paginas que eles exibem. Subsistemas, DLLs e serviços do modo usuário Todo esse carregamento dinâmico de código resultou em uma complexidade ainda maior para o sistema operacional, o gerenciamento de versões de bibliotecas não é apenas um problema de combinar um executável com as versões certas das DLLs, mas em alguns casos carregar varias versões da mesma DLL para um processo – o que a Microsoft chama de lado a lado. Um único programa pode hospedar duas bibliotecas de códigos dinâmicas diferentes, e cada uma pode querer carregar a mesma biblioteca do Windows – mas ter requisitos de versões diferentes para essa biblioteca. Subsistemas, DLLs e serviços do modo usuário Uma solução melhor seria hospedar código em processos separados. Mas a hospedagem de código fora dos processos resulta em desempenho mais baixo e implica modelos de programação mais complicados em muitos casos. A Microsoft ainda tem que desenvolver uma boa solução para toda essa complexidade no modo usuário. Isso faz com que alguém anseie pela relativa simplicidade do modo núcleo. Subsistemas, DLLs e serviços do modo usuário Uma das razoes para o modo núcleo ter menos complexidade que o modo usuário é que ele da suporte a poucas oportunidades de extensão fora do modelo de driver de dispositivo. O Windows Vista faz uso significativo de processos de serviços do modo usuário para estender a funcionalidade do sistema. Alguns desses serviços são fortemente ligados ao funcionamento dos componentes do modo núcleo, como o lsass.exe, que é o serviço de autenticação de segurança local, que gerencia os objetos de token que representam a identidade do usuário, bem como gerencia as chaves de codificação usadas pelo sistema de arquivos. Subsistemas, DLLs e serviços do modo usuário O gerenciador de recursos pronto para usar do modo usuário é responsável por determinar o driver correto a ser utilizado quando um novo dispositivo de hardware é encontrado, instalá-lo, e dizer ao núcleo para carregá-lo. Muitos outros recursos oferecidos por terceiros, como antivírus e gerenciador de direitos digitais, são implementados como uma combinação de drivers do modo núcleo e serviços do modo usuário. Dentro de cada um dos processos compartilhados de serviço, serviços individuais são carregados como DLLs. Eles, de modo geral, dividem um tanque de threads usando o recurso de tanque de threads do Win32, de modo que apenas um numero mínimo de threads precise ficar sendo executado por todos os serviços residentes. Subsistemas, DLLs e serviços do modo usuário O numero de serviços sendo executados de maneira constante no Windows é impressionante. No entanto, alguns desses serviços nunca recebem uma única solicitação e, quando o fazem, é provável que seja de um atacante tentando explorar uma vulnerabilidade. Como resultado, mais e mais serviços no Windows são desativados por padrão, em especial nas versões do Windows Server. Processos e Threads no Windows Vista No Windows Vista os processos são contentores para programas. Eles detêm o espaço de endereçamento virtual, os manipuladores que fazem referencia aos objetos do modo núcleo, e os threads. Em seu papel de contentores de threads, eles detêm recursos comuns usados para execução de threads, como o ponteiro para a estrutura de cota, o objeto de token compartilhado e parâmetros-padrão usados para inicializar os threads – incluindo a classe de escalonamento e prioridade. Processos e Threads no Windows Vista Os threads são a abstração do núcleo para escalonar a CPU no Windows. Prioridades são atribuídas para cada thread com base no valor da prioridade no processo que o contem. Cada thread tem duas pilhas separadas de chamadas, uma para execução no modo usuário e outra para o modo núcleo; há também um TEB (bloco de ambiente de thread – thread environment block) que mantêm os dados do modo usuário específicos ao thread, incluindo armazenamento por thread (armazenamento local de thread – thread local storage) e campos para o Win32, linguagem e localização cultural, e outros campos especializados que foram adicionados por vários outros recursos. Processos e Threads no Windows Vista Processos Os processos são criados por objetos de seção, cada um dos quais descreve um objeto de memória apoiado em um arquivo no disco. Quando um processo é criado o processo criador recebe um descritor para esse processo que lhe permite modificá-lo mapeando seções, alocando memória virtual, gravando parâmetros e dados de ambiente, duplicando identificadores de arquivo em sua tabela de descritores e criando threads. Isso é muito diferente de como os processos são criados no UNIX e reflete a diferença entre os sistemas pretendidos nos projetos originais do UNIX versus Windows. Processos e Threads no Windows Vista Tarefas e filamentos O Windows pode agrupar processos em tarefas, mas a abstração de tarefas não é muito genérica. A propriedade mais significativa das tarefas para o gerenciamento de recursos é que, uma vez que um processo esteja em uma tarefa, todos os threads dos processos que esse processo cria também estarão na tarefa. Não há como fugir. Processos e Threads no Windows Vista Tarefas e filamentos Um processo pode estar no maximo em uma tarefa. O uso de tarefas no Windows é raro As tarefas contem processos; os processos contem threads, mas os threads não contem filamentos. O relacionamento dos threads com filamentos é de modo geral de muitos para muitos. Processos e Threads no Windows Vista Tarefas e filamentos Os filamentos são criados alocando-se uma pilha e uma estrutura de dados de filamento do modo usuário para armazenar registradores e dados associados ao filamento. Os threads são convertidos em filamentos, mas estes podem também ser criados de modo independente dos threads. Esses filamentos não serão executados até que um filamento que já esteja sendo executado em um thread chame, de forma explicita SwitchToFiber para executar o filamento. A vantagem primaria dos filamentos é que o custo adicional da troca entre filamentos é muito mais baixo que o da troca entre threads. Uma troca de thread requer entrada e saída do núcleo. Uma troca de filamento grava e recupera alguns registradores sem qualquer mudança nos modos. Processos e Threads no Windows Vista Threads Cada processo normalmente inicializa com um thread, mas novos threads podem ser criados de maneira dinâmica. Os threads formam a base de escalonamento de CPU, já que o sistema operacional sempre seleciona um thread para ser executado, e não um processo. Como conseqüência todo thread tem um estado (pronto, em execução, bloqueado), ao passo que os processos não tem um estado de escalonamento. Processos e Threads no Windows Vista Threads Cada thread tem seu identificador, que é obtido do mesmo espaço que os identificadores do processo. Um thread normalmente é executado no modo usuário, mas quando ele faz uma chamada de sistema, muda para o modo núcleo e continua a ser executado como o mesmo thread com as mesmas propriedades e limites que tinha no modo usuário. Cada thread tem duas pilhas, uma para ser usada no modo usuário e outro para o modo núcleo. Processos e Threads no Windows Vista Threads É importante lembrar que os threads são um conceito de escalonamento, não um conceito de posse de recurso. Qualquer thread é capaz de acessar todos os objetos que pertencem ao processo. Alem dos threads normais que são executados nos processos do usuário, o Windows tem uma serie threads de sistema que são executados apenas no modo núcleo. Todos esses threads de sistema são executados em um processo especial, chamado processo de sistema. Esse processo não tem espaço de endereçamento no modo usuário. Ele fornece um ambiente no qual threads são executados quando não estão operando em nome de um processo especifico do modo usuário. Chamadas API de gerenciamento de tarefa, processo, thread e filamento A funcionalidade fornecida pela API do Windows podem ser agrupados em oito categorias: • Serviços de Base: Proporciona o acesso aos recursos fundamentais à disposição um sistema Windows. • Advanced Service: Proporcionar o acesso a funcionalidade que é uma adição no kernel Chamadas API de gerenciamento de tarefa, processo, thread e filamento Graphics Device Interface: Fornece a funcionalidade para saída de conteúdos gráficos para os monitores , impressoras e outros dispositivos de saída. Interface do usuário: Fornece a funcionalidade para criar e gerenciar tela janelas e controles mais básicos, como botões e barras de rolagem , receber mouse e teclado, e outras funcionalidades associadas com a GUI parte do Windows. Serviços de Rede: Dá acesso a várias redes capacidades do sistema operacional. Chamadas API de gerenciamento de tarefa, processo, thread e filamento Caixa de diálogo Biblioteca comum: Fornece as aplicações standard caixas de diálogo para abrir e salvar arquivos, escolher a cor e o tipo de letra, etc. Biblioteca de Controle comum: Dá acesso a alguns aplicativos de controles avançados fornecidos pelo sistema operacional. Windows Shell: Componente da API do Windows permite que aplicativos acessem a funcionalidade fornecida pelo shell do sistema operacional , bem como alterar e melhorar. Chamadas API de gerenciamento de tarefa, processo, thread e filamento Função da API do Win32 Descrição CreateProcess Cria um novo processo CreateThreads Cria um novo thread em um processo existente CreateFiber Cria um novo filamento ExitProcess Finaliza o processo aual e todos os seus threads ExitThread Finaliza este thread ExitFiber Finaliza este filamento SwitchToFiber Executa um filamento diferente no thread atual SetPriorityClass Configura a prioridade de um thread Escalonamento O windows não tem um thread de escalonamento central. Quando um thread não pode mais executar, o thread entra no modo núcleo e executa ele mesmo o escalonador para verificar qual thread deve ser executada. O thread executa o código do escalonador: 1. O thread atualmente em execução bloqueia em um semáforo, mutex, evento, E/S etc. 2. Ele sinaliza um objeto. 3. O quantum do thread em execução expira. O escalonador tambem pode ser chamado por: 1. Uma operação de E/S termina. 2. Uma espera temporizada expira. Escalonamento A API Win32 fornece dois ganchos para os processos influenciarem o escalonamento. A chamada SetPriorityClass – define as classes de prioridade de todos os threads no processo de quem chamou. A classe de prioridade determina as prioridades relativas do processo. Os valores permitidos são: tempo real, alta, acima do normal, normal, abaixo do normal e ociosa. A chamada SetThreadPriority – define a prioridade relativa de alguns threads, comparando aos outros threads do seu processo. Valores permitido: tempo crítico, mais alta, acima do normal, normal, abaixo do tempo, mais baixa e ociosa. Funcionamento do escalonamento O sistema tem 32 prioridades, numeradas de 0 a 31. O número na tabela determina a prioridade- base do thread. Todo thread tem uma prioridade atual. O algoritmo básico de escalonamento consiste em buscar no vetor desde a prioridade 31 até a 0. Assim que uma prioridade que não estiver vazia for encontrada, o thread no inicio da fila será selecionado e executado por um quantum. Se o quantum expira, o thread vai para o final da fila de seu nível de prioridade e o thread da frente é escolhido como próximo. Funcionamento do escalonamento Funcionamento do escalonamento Para aumentar a escalabilidade dos algoritmos de escalonamento em multiprocessadores com uma grande quantidade de processadores, o escalonador tenta não bloquear a trava que sincroniza o acesso ao vetor global de listas de prioridade. Em vez disso, ele verifica se pode despachar diretamente para o processador adequado um thread que esteja pronto para execução. Para cada thread, o escalonador mantém uma idéia de processador ideal e, sempre que possível, tenta agendar o thread para esse processador Funcionamento do escalonamento O escalonador sabe dos multiprocessadores nos quais cada CPU tem sua própria memória e pode executar programas armazenados em qualquer memoria, com um custo quando a memória não é local. São sistemas denominados NUMA (maquina de acesso não uniforme à memória). O escalonador tenta otimizar a colocação dos threads nessas máquinas. O gerenciador de memória tenta alocar páginas físicas no nó NUMA pertencente ao processador ideal para os threads quando sofrem falta de página. Funcionamento do escalonamento Funcionamento do escalonamento A figura mostra que na verdade há quatro categorias de prioridade: tempo real, usuário, zero e ociosa, que na verdade vale -1. A prioridade dos threads aumenta quando: Uma operação de E/S termina e libera um thread que está esperando. Um thread que esteja esperando em um semáforo, mutex ou outro evento. Esses não são definitivos. Tem efeito imediato e podem acarretar o reescalonamento de toda a CPU. Funcionamento do escalonamento Há um outro caso que o sistema se ocupa com as prioridades: Dois threads trabalhando juntos em um problema do tipo produtor consumidor. Gerenciamento de memória No windows Vista, todo processo usuário tem seu próprio espaço no endereçamento virtual. Alocação de endereço virtual Cada página de endereçamento virtual pode estar em três estados: inválida, reservada ou comprometida. Invalida: Não está atualmente mapeada para um objeto de seção de memória, e uma referencia a ela causa uma falta de pagina que acarreta uma violação de acesso. Comprometida: uma vez que o código ou os dados estejam mapeados em uma página virtual, esta página está comprometida. Reservada: Uma pagina virtual reservada é invalida, mas seus endereços virtuais nunca serão alocados pelo gerenciador de memória para nenhum outro propósito