Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

Introdução aos Sistemas Operacionais

Oi, Habr! Gostaria de chamar sua atenção para uma série de artigos-traduções de uma literatura interessante na minha opinião - OSTEP. Este material discute profundamente o trabalho de sistemas operacionais do tipo unix, ou seja, trabalhar com processos, vários agendadores, memória e outros componentes semelhantes que compõem um sistema operacional moderno. Você pode ver o original de todos os materiais aqui aqui. Por favor, note que a tradução foi feita de forma pouco profissional (com bastante liberdade), mas espero ter mantido o significado geral.

O trabalho de laboratório sobre este assunto pode ser encontrado aqui:

Outras partes:

Você também pode conferir meu canal em telegrama =)

Vejamos a abstração mais fundamental que o sistema operacional fornece aos usuários: o processo. A definição do processo é bastante simples - é programa em execução. O programa em si é algo sem vida localizado no disco - é um conjunto de instruções e possivelmente alguns dados estáticos esperando para serem iniciados. É o sistema operacional que pega esses bytes e os executa, transformando o programa em algo útil.
Na maioria das vezes, os usuários desejam executar mais de um programa ao mesmo tempo, por exemplo, você pode executar um navegador, um jogo, um reprodutor de mídia, um editor de texto e similares em seu laptop. Na verdade, um sistema típico pode executar dezenas ou centenas de processos simultaneamente. Este fato torna o sistema mais fácil de usar, você nunca precisa se preocupar se a CPU está livre, basta executar programas.

Isto levanta o problema: como proporcionar a ilusão de muitas CPUs? Como o sistema operacional pode criar a ilusão de um número quase infinito de CPUs, mesmo se você tiver apenas uma CPU física?

O sistema operacional cria essa ilusão por meio da virtualização da CPU. Ao iniciar um processo, depois interrompê-lo, iniciar outro processo e assim por diante, o sistema operacional pode manter a ilusão de que existem muitas CPUs virtuais, quando na verdade haverá um ou mais processadores físicos. Essa técnica é chamada divisão de recursos da CPU por tempo. Essa técnica permite que os usuários executem quantos processos simultâneos desejarem. O custo desta solução é o desempenho - pois se a CPU for compartilhada por vários processos, cada processo será processado mais lentamente.
Para implementar a virtualização da CPU, e especialmente para fazê-la bem, o sistema operacional precisa de suporte de baixo e de alto nível. O suporte de baixo nível é chamado mecanismos são métodos ou protocolos de baixo nível que implementam a parte necessária da funcionalidade. Um exemplo dessa funcionalidade é a troca de contexto, que dá ao sistema operacional a capacidade de interromper um programa e executar outro programa no processador. Esta divisão de tempo é implementada em todos os sistemas operacionais modernos.
Além desses mecanismos, há alguma lógica incorporada ao sistema operacional, na forma de “políticas”. Política é um certo algoritmo de tomada de decisão para o sistema operacional. Tais políticas, por exemplo, decidem qual programa deve ser iniciado primeiro (a partir de uma lista de comandos). Assim, por exemplo, este problema será resolvido por uma política chamada agendador (política de agendamento) e na hora de escolher uma solução, ela será guiada por dados como: histórico de inicialização (qual programa foi lançado por mais tempo nos últimos minutos), que carga esse processo carrega (que tipos de programas foram lançados), métricas de desempenho (se o sistema é otimizado para interação interativa ou para taxa de transferência) e assim por diante.

Abstração: processo

A abstração de um programa em execução executado pelo sistema operacional é o que chamamos processo. Conforme mencionado anteriormente, um processo é simplesmente um programa em execução, em qualquer período instantâneo de tempo. Um programa com o qual podemos obter informações resumidas dos diversos recursos do sistema que este programa acessa ou afeta durante sua execução.
Para entender os componentes do processo, você precisa entender os estados do sistema: o que o programa pode ler ou alterar durante sua operação. A qualquer momento, você precisa entender quais elementos do sistema são importantes para a execução do programa.
Um dos elementos óbvios do estado do sistema que o processo inclui é memória. As instruções estão localizadas na memória. Os dados que o programa lê ou grava também estão localizados na memória. Assim, a memória que um processo pode endereçar (chamada espaço de endereço) faz parte do processo.
Também fazem parte do estado do sistema os registros. Muitas instruções visam alterar o valor dos registradores ou ler seu valor e, assim, os registradores também se tornam uma parte importante da operação do processo.
Deve-se notar que o estado da máquina também é formado a partir de alguns registros especiais. Por exemplo, IP - ponteiro de instrução — um ponteiro para a instrução que o programa está executando atualmente. Há também ponteiro de pilha e relacionado a isso ponteiro de quadro, que são usados ​​para gerenciar: parâmetros de função, variáveis ​​locais e endereços de retorno.
Finalmente, os programas frequentemente acessam ROM (memória somente leitura). Essas informações de “E/S” (entrada/saída) devem incluir uma lista de arquivos atualmente abertos pelo processo.

API de processo

Para melhorar nossa compreensão de como funciona o processo, vamos estudar exemplos de chamadas de sistema que devem ser incluídas em qualquer interface de sistema operacional. Essas APIs estão disponíveis de uma forma ou de outra em qualquer sistema operacional.

Crie (criação): O sistema operacional deve incluir algum método que permita criar novos processos. Quando você insere um comando no terminal ou inicia um aplicativo clicando duas vezes em um ícone, uma chamada é enviada ao sistema operacional para criar um novo processo e, em seguida, iniciar o programa especificado.
Remoção: como existe uma interface para criar um processo, o sistema operacional também deve fornecer a capacidade de forçar a remoção de um processo. A maioria dos programas inicia e termina naturalmente por conta própria enquanto são executados. Caso contrário, o usuário gostaria de poder matá-los e, portanto, uma interface para interromper o processo seria útil.
Espere (esperando): Às vezes é útil aguardar a conclusão de um processo, portanto, são fornecidas algumas interfaces que fornecem a capacidade de esperar.
Controle diverso (vários controles): Além de matar e aguardar o processo, existem também vários outros métodos de controle. Por exemplo, a maioria dos sistemas operacionais oferece a capacidade de congelar um processo (interromper sua execução por um determinado período) e depois retomá-lo (continuar a execução).
Status (estado): Existem várias interfaces para obter algumas informações sobre o status de um processo, como há quanto tempo ele está em execução ou em que estado se encontra atualmente.

Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

Criação de Processo: Detalhes

Uma das coisas interessantes é como exatamente os programas são transformados em processos. Especialmente como o sistema operacional seleciona e executa o programa. Como exatamente o processo é criado.
Primeiro de tudo, o sistema operacional deve carregar o código do programa e os dados estáticos na memória (no espaço de endereço do processo). Os programas geralmente estão localizados em um disco ou unidade de estado sólido em algum formato executável. Assim, o processo de carregamento de programas e dados estáticos na memória exige que o sistema operacional seja capaz de ler esses bytes do disco e colocá-los em algum lugar da memória.

Nos primeiros sistemas operacionais, o processo de carregamento era feito com entusiasmo, o que significa que todo o código era carregado na memória antes do lançamento do programa. Os sistemas operacionais modernos fazem isso preguiçosamente, ou seja, carregando pedaços de código ou dados apenas quando o programa os exige durante sua execução.

Depois que o código e os dados estáticos são carregados na memória do sistema operacional, há mais algumas coisas que precisam ser feitas antes que o processo possa ser executado. Alguma quantidade de memória deve ser alocada para a pilha. Os programas usam a pilha para variáveis ​​locais, parâmetros de função e endereços de retorno. O sistema operacional aloca essa memória e a fornece ao processo. A pilha também pode ser alocada com alguns argumentos, especificamente preenche os parâmetros da função main(), por exemplo, com um array de argc e argv.

O sistema operacional também pode alocar alguma memória para o heap do programa. O heap é usado por programas para solicitar explicitamente dados alocados dinamicamente. Os programas solicitam este espaço chamando a função malloc () e limpa explicitamente chamando a função gratuitamente(). O heap é necessário para estruturas de dados como planilhas vinculadas, tabelas hash, árvores e outras. A princípio, uma pequena quantidade de memória é alocada para o heap, mas com o tempo, à medida que o programa é executado, o heap pode solicitar mais memória por meio da chamada da API da biblioteca malloc(). O sistema operacional está envolvido no processo de alocação de mais memória para ajudar a atender essas chamadas.

O sistema operacional também executará tarefas de inicialização, particularmente aquelas relacionadas a E/S. Por exemplo, em sistemas UNIX, cada processo por padrão possui 3 descritores de arquivo abertos, para entrada, saída e erro padrão. Esses identificadores permitem que os programas leiam as entradas do terminal, bem como exibam informações na tela.

Assim, ao carregar código e dados estáticos na memória, criar e inicializar a pilha e realizar outros trabalhos relacionados à execução de tarefas de E/S, o sistema operacional prepara o palco para a execução do processo. Finalmente, resta uma última tarefa: executar o programa através de seu ponto de entrada, chamado de função main(). Ao executar a função main(), o sistema operacional transfere o controle da CPU para o processo recém-criado, assim o programa começa a ser executado.

Estado do processo

Agora que entendemos o que é um processo e como ele é criado, vamos listar os estados do processo em que ele pode estar. Na sua forma mais simples, um processo pode estar em um destes estados:
Corrida. Durante a execução, o processo é executado no processador. Isso significa que as instruções estão sendo executadas.
Pronto. No estado pronto, o processo está pronto para ser executado, mas por algum motivo o sistema operacional não o executa no horário especificado.
Bloqueado. No estado bloqueado, um processo realiza algumas operações que o impedem de estar pronto para execução até que algum evento ocorra. Um exemplo comum é quando um processo inicia uma operação de E/S, ele fica bloqueado para que algum outro processo possa usar o processador.

Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

Você pode imaginar esses estados na forma de um gráfico. Como podemos ver na imagem, o estado do processo pode mudar entre RUNNING e READY a critério do SO. Quando o estado de um processo muda de READY para RUNNING, significa que o processo foi agendado. Na direção oposta - removido do layout. No momento em que um processo fica BLOQUEADO, por exemplo, eu inicio uma operação de IO, o SO irá mantê-lo neste estado até que algum evento ocorra, por exemplo a conclusão do IO. neste momento a transição para o estado READY e possivelmente imediatamente para o estado RUNNING se o SO assim decidir.
Vejamos um exemplo de como dois processos se movem através desses estados. Para começar, vamos imaginar que ambos os processos estão em execução e cada um usa apenas a CPU. Nesse caso, seus estados ficarão assim.

Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

No exemplo a seguir, o primeiro processo, após algum tempo de execução, solicita IO e entra no estado BLOCKED, permitindo a execução de outro processo (FIG 1.4). O sistema operacional vê que o processo 0 não está usando a CPU e inicia o processo 1. Enquanto o processo 1 está em execução, o IO é concluído e o status do processo 0 muda para PRONTO. Finalmente, o processo 1 foi concluído e, após a conclusão, o processo 0 inicia, executa e finaliza seu trabalho.

Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

Estrutura de dados

O próprio sistema operacional é um programa e, como qualquer outro programa, possui algumas estruturas de dados importantes que rastreiam várias informações relevantes. Para rastrear o estado de cada processo, o sistema operacional suportará alguns lista de processos para todos os processos no estado READY e algumas informações adicionais para rastrear os processos que estão em execução no momento. Além disso, o sistema operacional deve monitorar processos bloqueados. Após a conclusão do IO, o sistema operacional deve ativar o processo necessário e colocá-lo em um estado pronto para execução.

Por exemplo, o sistema operacional deve preservar o estado dos registradores do processador. No momento em que o processo para, o estado dos registradores é armazenado no espaço de endereço do processo, e no momento em que sua operação continua, os valores dos registradores são restaurados e assim dá-se continuidade à execução deste processo.

Além dos estados pronto, bloqueado e em execução, existem alguns outros estados. Às vezes, no momento da criação, um processo pode estar no estado INIT. Por fim, um processo pode ser colocado no estado FINAL quando já foi concluído, mas suas informações ainda não foram apagadas. Em sistemas UNIX este estado é chamado processo zumbi. Este estado é útil para casos em que um processo pai deseja saber o código de retorno de um filho, por exemplo, geralmente 0 sinaliza um sucesso e 1 um erro, mas os programadores podem emitir códigos de saída adicionais para sinalizar problemas diferentes. Quando o processo pai termina, ele faz uma chamada final do sistema, como wait(), para aguardar o término do processo filho e sinalizar ao sistema operacional que ele pode limpar quaisquer dados associados ao processo encerrado.

Sistemas operacionais: três peças fáceis. Parte 2: Abstração: Processo (tradução)

Pontos principais da palestra:

processo — a principal abstração de um programa em execução no sistema operacional. A qualquer momento, um processo pode ser descrito por seu estado: o conteúdo da memória em seu espaço de endereço, o conteúdo dos registradores do processador, incluindo ponteiro de instrução e ponteiro de pilha, e informações de E/S, como arquivos abertos sendo lidos ou gravados.
API de processo consiste em chamadas que os programas podem fazer aos processos. Normalmente são chamadas de criação, exclusão ou outras.
● O processo está em um dos vários estados, incluindo em execução, pronto, bloqueado. Vários eventos, como agendamento, exceções de agendamento ou esperas, podem alterar o estado de um processo de um para outro.
Lista de processos contém informações sobre todos os processos do sistema. Cada entrada nele é chamada de bloco de controle de processo, que na realidade é uma estrutura que contém todas as informações necessárias sobre um processo específico. 

Fonte: habr.com

Adicionar um comentário