Introdução aos sistemas operacionais
Olá Habr! Quero chamar sua atenção para uma série de artigos - traduções de uma literatura interessante em minha opinião - OSTEP. Este artigo discute profundamente o trabalho de sistemas operacionais semelhantes a unix, ou seja, trabalha com processos, vários agendadores, memória e outros componentes similares que compõem o sistema operacional moderno. O original de todos os materiais que você pode ver
aqui . Observe que a tradução foi feita de maneira não profissional (muito livremente), mas espero ter mantido o significado geral.
O trabalho de laboratório sobre este assunto pode ser encontrado aqui:
Outras partes:
E você pode olhar para o meu canal no
telegrama =)
Considere a abstração mais fundamental que o sistema operacional fornece aos usuários: um processo. Definir um processo é bastante simples - é um
programa de trabalho . O programa em si é algo inanimado localizado no disco - é um conjunto de instruções e, possivelmente, algum tipo de dado estático aguardando o lançamento. É o sistema operacional que pega esses bytes e os lança, convertendo o programa em algo útil.
Na maioria das vezes, os usuários desejam executar mais de um programa por vez, por exemplo, você pode executar um navegador, jogo, media player, editor de texto e similares no seu laptop. De fato, um sistema típico pode executar dezenas e centenas de processos simultaneamente. Esse fato facilita o uso do sistema, você nunca precisa se preocupar se a CPU está livre, basta executar os programas.
Isso levanta o problema: como fornecer a ilusão de várias CPUs? Como o sistema operacional cria a ilusão de uma quantidade quase infinita de CPUs, mesmo que você tenha apenas uma CPU física?O sistema operacional cria essa ilusão através da virtualização da CPU. Iniciando um processo, parando-o, iniciando outro processo e assim por diante, o sistema operacional pode suportar a ilusão de que existem muitas CPUs virtuais, embora, na verdade, sejam um ou mais processadores físicos. Essa técnica é chamada de
compartilhamento de tempo da CPU . Essa técnica permite que os usuários executem quantos processos simultâneos desejarem. O custo dessa solução é o desempenho - porque 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ê-lo bem, o sistema operacional precisa de suporte de nível baixo e alto. O suporte de baixo nível é chamado de
mecanismos - esses são métodos ou protocolos de baixo nível que implementam a parte necessária da funcionalidade. Um exemplo dessa funcionalidade é a alternância de contexto, que permite ao sistema operacional interromper um programa e executar outro programa no processador. Essa divisão de tempo é implementada em todos os sistemas operacionais modernos.
No topo desses mecanismos há alguma lógica embutida no sistema operacional, na forma de "políticas".
Uma política é um determinado algoritmo de tomada de decisão por um sistema operacional. Tais políticos, por exemplo, decidem qual programa executar (da lista de comandos) em primeiro lugar. Portanto, por exemplo, uma política chamada política de
agendamento resolverá esse problema e, ao escolher uma solução, ela será guiada por dados como: histórico de inicialização (qual programa está sendo executado por mais tempo nos últimos minutos), que tipo de carga esse processo realiza (que tipos de programas foram lançados) ), métricas de desempenho (se o sistema é otimizado para interação interativa ou largura de banda) e assim por diante.
Abstração: processo
A abstração de um programa em execução realizado pelo sistema operacional é o que chamamos de
processo . Como mencionado anteriormente, um processo é simplesmente um programa de trabalho, a qualquer período instantâneo de tempo. Um programa com o qual podemos obter informações resumidas de vários recursos do sistema e para os quais esse programa aborda ou afeta durante sua execução.
Para entender os componentes do processo, você precisa entender o estado do sistema: 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 é a
memória . As instruções estão na memória. Os dados que o programa lê ou grava também estão localizados na memória. Assim, a memória que o processo pode endereçar (o chamado espaço de endereçamento) faz parte do processo.
Os registros também fazem parte do estado do sistema. Muitas instruções têm como objetivo alterar o significado dos registros ou ler seu significado, e assim os registros também se tornam uma parte importante do processo.
Note-se 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 no momento. Há também um
ponteiro de pilha e o
ponteiro de quadro associado, que são usados para controlar: parâmetros de função, variáveis locais e endereços de retorno.
Por fim, os programas geralmente acessam a ROM (memória somente leitura). Essas informações sobre “E / S” (entrada e saída) devem incluir uma lista de arquivos atualmente abertos pelo processo.
API de processo
Para melhorar o entendimento do processo, examinemos exemplos de chamadas do sistema que devem ser incluídas em qualquer interface do sistema operacional. Essas APIs, de uma forma ou de outra, estão disponíveis em qualquer sistema operacional.
●
Criar : o sistema operacional deve incluir algum método que permita criar novos processos. Quando você insere um comando no terminal ou inicia o aplicativo clicando duas vezes no ícone, um apelo é enviado ao sistema operacional para criar um novo processo e, em seguida, iniciar o programa especificado.
●
Exclusão : assim que houver uma interface para criar um processo, o sistema operacional também deverá fornecer a capacidade de forçar a exclusão do processo. A maioria dos programas será naturalmente lançada e concluída por eles mesmos à medida que forem executados. Caso contrário, o usuário gostaria de poder matá-los e, portanto, a interface para interromper o processo não será supérflua.
●
Aguardar : Às vezes, é útil aguardar a conclusão do processo; portanto, são fornecidas algumas interfaces que permitem aguardar.
●
Controle misto (controle diverso): além de matar e aguardar o processo, existem vários outros métodos de controle. Por exemplo, a maioria dos sistemas operacionais fornece a capacidade de congelar um processo (interrompê-lo por um determinado período) e, em seguida, retomá-lo (continuar a execução)
●
Status : existem várias interfaces para receber algumas informações sobre o status do processo, como a duração de sua operação ou em que estado ele está agora.

Criação de processo: detalhes
Uma das coisas interessantes é como exatamente os programas são transformados em processos. Especialmente como o sistema operacional pega e executa o programa. Como exatamente o processo é criado.
Primeiro, 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 no disco ou em uma unidade de estado sólido em algum formato executável. Portanto, o processo de carregamento de um programa e dados estáticos na memória requer que o sistema operacional leia esses bytes do disco e os coloque em algum lugar da memória.
Nos sistemas operacionais antigos, o processo de inicialização era executado com entusiasmo, o que significa que o código foi carregado na memória totalmente antes do início do programa. Os SOs modernos fazem isso preguiçosamente, ou seja, carregando partes de código ou dados somente quando são necessários pelo programa durante sua execução.
Depois que o código e os dados estáticos são carregados na memória do sistema operacional, você precisa fazer mais algumas coisas antes de iniciar o processo. Uma certa 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 a matriz argc e argv.
O sistema operacional também pode alocar uma certa quantidade de memória para a pilha do programa.
A pilha é usada por programas para dados explicitamente solicitados alocados dinamicamente . Os programas solicitam esse espaço chamando a função
malloc () e limpam explicitamente chamando a função
free () . É necessário um heap para estruturas de dados, como planilhas vinculadas, tabelas de hash, árvores e outras. Inicialmente, uma pequena quantidade de memória é alocada no heap, mas com o tempo, durante a operação do programa, o heap pode solicitar mais memória por meio da API da biblioteca chamada malloc (). O sistema operacional está envolvido no processo de alocação de mais memória para ajudar a enfrentar esses desafios.
O sistema operacional também executará tarefas de inicialização, em particular aquelas relacionadas a E / S. Por exemplo, nos sistemas UNIX, cada processo possui 3 descritores de arquivos abertos por padrão, para fluxos de entrada, saída e erro padrão. Esses descritores permitem que os programas leiam as entradas do terminal, além de exibir informações na tela.
Assim, carregando o código e os dados estáticos na memória, criando e inicializando a pilha e também executando outro trabalho relacionado à execução de tarefas de E / S, o SO prepara o site para o processo. No final, a última tarefa permanece: executar o programa através de seu ponto de entrada, chamado de função main (). Prosseguindo para a função main (), o sistema operacional transfere o controle da CPU para o processo recém-criado, para que o programa comece a ser executado.
Status do processo
Agora que entendemos o que é um processo e como ele é criado, listamos os estados do processo em que ele pode ser. Na sua forma mais simples, um processo pode estar em um destes estados:
● Em
execução . No estado de execução, o processo é executado no processador. Isso significa que as instruções estão sendo executadas.
●
Pronto . Em um estado pronto, o processo está pronto para iniciar, mas, por algum motivo, o SO não o executa em um determinado momento.
●
Bloqueado . Em um estado bloqueado, o processo executa algumas operações que impedem que esteja pronto para execução até que um evento ocorra. Um exemplo comum é quando um processo inicia uma operação de E / S, fica bloqueado e, portanto, algum outro processo pode usar o processador.

Você pode imaginar esses estados na forma de um gráfico. Como podemos ver na figura, o estado do processo pode mudar entre RUNNING e READY, a critério do sistema operacional. Quando o estado de um processo muda de READY para RUNNING, isso significa que o processo foi agendado. Na direção oposta - removido do layout. No momento em que o processo fica BLOQUEADO, por exemplo, inicio uma operação de E / S, o sistema operacional o manterá nesse estado até que ocorra algum evento, por exemplo, a conclusão de E / S. nesse momento, faça a transição para o estado READY e, possivelmente, instantaneamente para o estado RUNNING, se o SO decidir.
Vamos dar uma olhada em um exemplo de como dois processos passam por esses estados. Primeiro, imagine que ambos os processos estejam em execução e cada um use apenas a CPU. Nesse caso, seus estados terão a seguinte aparência.

No exemplo a seguir, depois de um tempo, o primeiro processo solicita um IO e entra no estado BLOCKED, dando ao outro processo a capacidade de iniciar (FIG. 1.4). O SO vê que o processo 0 não usa a CPU e inicia o processo 1. Durante a execução do processo 1 - IO termina e o status do processo 0 muda para READY. Finalmente, o processo 1 é concluído e, ao final, o processo 0 inicia, executa e finaliza seu trabalho.

Estrutura de dados
O sistema operacional em si é um programa e, como qualquer outro programa, possui algumas estruturas de dados importantes que rastreiam uma variedade de informações relevantes. Para rastrear o status de cada processo no sistema operacional, será suportada uma certa
lista de processos para todos os processos no estado READY e algumas informações adicionais para rastrear processos em execução no momento. Além disso, o sistema operacional deve rastrear e bloquear os processos. Após concluir a IO, o sistema operacional deve despertar o processo desejado e colocá-lo em um estado de prontidão para o lançamento.
Portanto, por exemplo, o sistema operacional deve salvar o estado dos registros do processador. No momento em que o processo é interrompido, o estado dos registros é salvo no espaço de endereço do processo e, no momento de sua continuação, é possível restaurar os valores dos registros e, assim, continuar o processo.
Além dos estados pronto, bloqueado e em execução, existem outros estados. Às vezes, no momento da criação, um processo pode ter um estado INIT. Finalmente, um processo pode ser colocado no estado FINAL quando já estiver concluído, mas as informações sobre ele ainda não foram limpas. Nos sistemas UNIX, esse estado é chamado de
processo zumbi . Esse estado é útil nos casos em que o processo pai deseja saber o código de retorno do descendente, por exemplo, geralmente 0 indica conclusão bem-sucedida e 1 indica um erro, mas os programadores podem criar códigos de saída adicionais, sinalizando vários problemas. Após a conclusão, o processo pai faz a última chamada do sistema, por exemplo, wait (), para aguardar a conclusão do processo descendente e sinalizar ao SO que quaisquer dados associados ao processo concluído podem ser limpos.

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 o ponteiro de instruções e o ponteiro de pilha, também com informações sobre E / S, por exemplo, arquivos abertos que são lidos ou gravados.
● A
API de processo consiste em chamadas que os programas podem fazer em relação a processos. Geralmente, essas são chamadas para criar, excluir ou outras.
● Um processo está em um dos muitos estados, incluindo em execução, pronto, bloqueado. Vários eventos, como planejamento, exclusão de planejamento ou expectativas, podem converter o estado de um processo de um para outro.
● A
lista de processos contém informações sobre todos os processos no 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.