Trabalho de LAPRO II

Trabalho Prático do Semestre - Laboratório de Programação II

Simulador de Gerência de Processador

1. Descrição do problema

Nas sessões seguintes é descrito o problema, ou seja, o que é um processo e como é feita a gerência do processador por parte de um sistema operacional. O texto abaixo foi extraído do livro "Sistemas Operacionais", da Série Livros Didáticos do Instituto de Informática da UFRGS, escrito pelos professores Rômulo Silva de Oliveira, Alexandre da Silva Carissimi e Simão Sirineo Toscani e editado pela Editora Sagra Luzzatto.

1.1. O conceito de processo

Em sistemas operacionais é conveniente diferenciar um programa de sua execução. Por exemplo, o mesmo programa pode estar sendo executado por vários usuários ao mesmo tempo. Para tanto é usado o conceito de processo. Não existe uma definição objetiva, aceita por todos, para a idéia de processo. Na maioria das vezes, um processo é definido como "um programa em execução". O conceito de processo é bastante abstrato, mas essencial no estudo de sistemas operacionais.

Um programa é uma seqüência de instruções, é algo passivo dentro do sistema. Ele não altera o seu próprio estado. O processo é um elemento ativo. O processo altera o seu estado à medida que executa um programa. é o processo que faz chamadas de sistema, ao executar os programas.

É possível que vários processos executem o mesmo programa ao mesmo tempo. Por exemplo, diversos usuários podem estar utilizando simultaneamente o editor de texto favorito da instalação. Existe um único programa "editor de texto". Para cada usuário, existe um processo executando o programa. Cada processo representa uma execução independente do editor de textos. Todos os processos utilizam uma mesma cópia do código do editor de textos, porém cada processo trabalha sobre uma área de variáveis privativa.

1.2. Ciclos de um processo

Processos são criados e destruídos. O momento e a forma pela qual eles são criados e destruídos depende do sistema operacional em consideração. Alguns sistemas trabalham com um número fixo de processos. Por exemplo, um processo para cada terminal do computador. Nesse caso, todos os processos são criados na inicialização do sistema. Eles somente são destruídos quando o próprio sistema é desligado.

Outra forma de trabalhar com os processos é associá-los a uma sessão de trabalho. Um usuário abre uma sessão de trabalho fornecendo ao sistema seu código de usuário e, possivelmente, uma senha. A senha é necessária para que cada usuário limite o acesso de outros usuários aos seus arquivos. O sistema operacional verifica a validade da senha e cria um processo para atender o usuário. Provavelmente, o primeiro programa a ser executado pelo processo é o interpretador de comandos. No momento em que o usuário executa o comando "fim de sessão de trabalho", o processo associado à sessão é destruído.

A forma mais flexível de operação é permitir que processos possam ser criados livremente, através de chamadas de sistema. Além da chamada de sistema "cria processo", serão necessárias chamadas para "autodestruição do processo" e também para "eliminação de outro processo".

Após ter sido criado, o processo passa a ocupar processador. Em determinados momentos, ele deixa de ocupar o processador para realizar uma operação de E/S. Os momentos em que um processo não está esperando por E/S, ou seja, em que ele deseja ocupar o processador, são chamados de "ciclos de processador". Quando o processo está esperando por uma operação de E/S, ele está em um "ciclo de E/S". A chamada de sistema é o evento que termina o ciclo de processador em andamento e inicia um ciclo de E/S. A conclusão da chamada de sistema faz o caminho inverso. O primeiro ciclo da vida de um processo será necessariamente um ciclo de processador. Para entrar em um ciclo de E/S é necessário executar ao menos uma instrução. No caso, a instrução que faz a chamada de sistema.

1.3. Estados de um processo

Após ser criado, o processo entra em um ciclo de processador. Ele precisa de processador para executar. Entretanto, o processador poderá estar ocupado com outro processo, e ele deverá esperar. Diversos processos podem estar nesse mesmo estado. Por exemplo, imagine que o processo 1 está acessando um periférico. O processo 2 está executando. Quando termina a E/S do processo 1, ele precisa de processador para voltar a executar. Como ele está ocupado com o processo 2, o processo 1 deverá esperar. Por alguma razão, o sistema operacional pode decidir executar o processo 1 imediatamente. Entretanto, o problema não muda. Agora é o processo 2 quem deverá esperar até que o processador fique livre.

Em máquinas multiprocessadoras existem diversos processadores. Nesse caso, diversos processos executam ao mesmo tempo. Porém, essa não é a situação mais comum. Vamos supor que existe um único processador no computador. Nesse caso, é necessário manter uma fila com os processos aptos a ganhar o processador. Essa fila é chamada "fila de aptos" (ready queue).

A Figura abaixo ilustra essa situação. O processo 1 ocupa o processador, enquanto os processos 2 e 3 esperam na fila de aptos. Os processos na fila do processador estão no estado apto (ready). Um único processo ocupa o processador a cada instante. O processo que ocupa o processador está no estado executando (running). Na figura, o processo 1 está no estado executando, enquanto os processos 2 e 3 estão no estado apto.


Fila de processos esperando pelo processador

A próxima figura mostra o diagrama de estados de um processo. No estado executando, um processo pode fazer chamadas de sistema. Até a chamada de sistema ser atendida, o processo não pode continuar sua execução. Ele fica bloqueado e só volta a disputar o processador após a conclusão da chamada. Enquanto espera pelo término da chamada de sistema, o processo está no estado bloqueado (blocked).


Diagrama de estados de um processo

A mudança de estado de qualquer processo é iniciada por um evento. Esse evento aciona o sistema operacional, que então altera o estado de um ou mais processos. Como visto antes, a transição do estado executando para bloqueado é feita através de uma chamada de sistema. Uma chamada de sistema é necessariamente feita pelo processo no estado executando. Ele fica no estado bloqueado até o atendimento. Com isso, o processador fica livre. O sistema operacional então seleciona um processo da fila de aptos para receber o processador. O processo selecionado passa do estado de apto para o estado executando. O módulo do sistema operacional que faz essa seleção é chamado de escalonador (scheduler).

Outro tipo de evento corresponde às interrupções do hardware. Elas, em geral, informam o término de uma operação de E/S. Isso significa que um processo bloqueado será liberado. O processo liberado passa do estado de bloqueado para o estado de apto. Ele volta a disputar o processador com os demais da fila de aptos.

Muitos sistemas procuram evitar que um único processo monopolize a ocupação do processador. Se um processo está há muito tempo no processador, ele volta para o fim da fila de aptos. Um novo processo da fila de aptos ganha o processador. Dessa forma, cada processo tem a chance de executar um pouco. Esse mecanismo cria um caminho entre o estado executando e o estado apto. A Figura abaixo mostra o diagrama de estados dos processos com esses novos caminhos.


Novo diagrama de estados de um processo

1.4. Bloco descritor de processo

Como foi visto,  processos são interrompidos e mais tarde continuados. Por exemplo, suponha que o processo 1, executando, faça uma chamada de sistema. Ele é bloqueado, e um processo 2 passa a executar. Quando ocorrer a interrupção causada pelo periférico, uma possibilidade é suspender o processo 2 e retomar o processo 1. A maioria dos processos que estão na fila de aptos já executaram algum tempo. Eles esperam para receber o processador novamente. A única exceção são os processos novos, que entram no primeiro ciclo de processador.

Existem várias informações que o sistema operacional deve manter a respeito dos processos. No "programa" sistema operacional, um processo é representado por um registro. Esse registro é chamado de bloco descritor de processo ou simplesmente descritor de processo (DP). No DP, fica tudo que o sistema operacional precisa saber sobre o processo. Abaixo está uma lista de campos normalmente encontrados no descritor de processo:

Um processo quase sempre faz parte de alguma fila. Em geral, os próprios descritores de processo são utilizados como elementos dessas filas. Antes de ser criado, o descritor do processo faz parte de uma fila de descritores livres. Após a criação, o seu descritor é colocado na fila de aptos. Normalmente, essa fila é mantida na ordem em que os processos deverão receber o processador. O primeiro descritor da fila corresponde ao processo em execução. Ao fazer uma chamada de sistema associada com uma operação de E/S, o descritor do processo em execução é retirado da fila de aptos e inserido na fila associada ao periférico. O contexto de execução do processo é salvo no seu próprio descritor. Após a conclusão da operação de E/S, o seu descritor volta para a fila de aptos. Quando o processo é destruído, o descritor volta para a fila de descritores livres.

Na prática, descritores não são copiados. Todas as filas são implementadas como listas encadeadas. A passagem do descritor de uma fila para a outra é feita através da manipulação de apontadores.

Em muitos sistemas, existe um número fixo de descritores. Ele corresponde ao número máximo de processos que podem existir no sistema. Outros sistemas utilizam alocação dinâmica de memória para criar descritores. Nesse caso, não existe um limite para o número de descritores de processos. As próprias características físicas do equipamento, tais como tamanho da memória principal e velocidade do processador, irão estabelecer limites quanto ao número máximo de processos. Quando alocação dinâmica de memória é utilizada na criação de blocos descritores de processos, é importante que a memória alocada fique dentro da área protegida do sistema operacional. Os descritores de processos contêm informações vitais para a operação do sistema. Em hipótese alguma, eles podem ser alterados por um processo de usuário.

Na inicialização do sistema, todos os descritores de processo podem ser encadeados, para formar uma "lista de descritores livres". O início dessa lista é apontado por "desc_livre".

O apontador "espera_cpu" indica o início da lista de processos que esperam pelo processador. O descritor do processo que está executando é mantido à parte, apontado por "usando_cpu". Outra solução é fazer com que o processo que está com o processador ocupe a primeira posição da lista apontada por "espera_cpu". Nesse caso, o apontador "usando_cpu" não é necessário.

Para criar um processo, um descritor é retirado da lista apontada por "desc_livre". Se "desc_livre" contém null, a "lista de descritores livres" está vazia. Nesse caso, o processo não poderá ser criado. O próximo passo é completar os campos do descritor alocado com valores apropriados. Por exemplo, o programa a ser executado pelo processo deve ser localizado no disco, e uma área de memória grande o suficiente para ele deve ser alocada. O programa pode então ser carregado do disco para a memória principal. Essas tarefas exigem a participação dos módulos de gerência de memória e sistema de arquivos.

Quando todos os campos estiverem preenchidos, o descritor do processo é inserido na "lista de espera pelo processador", apontada por "espera_cpu". A partir desse momento, o processo passa a disputar tempo de processador, junto com os demais. Em outras palavras, o processo foi criado.

O procedimento de criação de processo que foi descrito é uma simplificação do que acontece em sistemas reais. Na prática, fatores como a arquitetura do computador e a forma como os diversos módulos do sistema operacional relacionam-se determinam o procedimento exato a ser adotado. Entretanto, o procedimento descrito deixa claro que a criação de um processo, com respeito a gerência do processador, corresponde a uma manipulação de registros e listas encadeadas.

As operações necessárias para a destruição de um processo são semelhantes. Primeiramente, todos os recursos que o processo havia alocado devem ser liberados. Por exemplo, memória principal, impressora, arquivos, etc. Essa etapa corresponde à limpeza do ambiente após a morte do processo. Depois, o seu descritor de processo é retirado da lista em que está e inserido novamente na "lista de descritores livres". Nesse momento, o processo deixa de existir. O descritor será reaproveitado na criação de um novo processo.

2. O trabalho

Com base na descrição do funcionamento de um gerenciador de processos (na seção acima), implemente um simulador de um gerenciador de processos simplificado para um sistema operacional fictício (Fake Operating System). O sistema FOS considera que apenas 15 descritores de processos podem existir (considerando aqueles em uso e os livres). Através de modelagem orientada a objetos, deverão ser implementadas as seguintes estruturas:

O programa deverá:

Importante:

3. Avaliação

O trabalho deverá ser realizado individualmente e apresentado para o professor nas datas abaixo.

Parte 1: 17/04/2002

Parte 2: 22/05/2002

Parte 3: 03/07/2002

Critérios para Avaliação:

Como entregar: