Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (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:

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

operação do programa

O que acontece quando um programa está em execução? Um programa em execução faz uma coisa simples - executa instruções. A cada segundo, milhões e possivelmente bilhões de instruções são recuperadas pelo processador da RAM, que por sua vez as decodifica (por exemplo, reconhece a que tipo essas instruções pertencem) e as executa. Isso pode incluir dois números, acessar a memória, verificar uma condição, pular para uma função e assim por diante. Após a execução de uma instrução, o processador procede à execução de outra. E assim instrução após instrução, elas são executadas até que o programa termine.

Este exemplo é naturalmente considerado simplificado - na verdade, para acelerar o processador, o hardware moderno permite executar instruções fora de hora, calcular resultados possíveis, executar instruções simultaneamente e truques semelhantes.

Modelo Von Neumann de computação

A forma simplificada de trabalho descrita por nós é semelhante ao modelo de computação de Von Neumann. Von Neumann é um dos pioneiros dos sistemas de computador, ele também é um dos autores da teoria dos jogos. Enquanto o programa está em execução, vários outros eventos ocorrem, muitos outros processos e lógica de terceiros funcionam, cujo principal objetivo é simplificar o lançamento, operação e manutenção do sistema.

Existe um conjunto de softwares responsáveis ​​por tornar os programas fáceis de executar (ou mesmo permitir que vários programas sejam executados ao mesmo tempo), que permite que os programas compartilhem a mesma memória e se comuniquem com diferentes dispositivos. Esse conjunto de software (software) é essencialmente chamado de sistema operacional e suas tarefas incluem monitorar se o sistema funciona de maneira correta e eficiente, além de garantir que o sistema seja fácil de gerenciar.

Sistema operacional

Um sistema operacional, abreviado como SO, é um conjunto de programas inter-relacionados projetados para gerenciar os recursos do computador e organizar a interação do usuário com um computador..

O SO atinge sua eficácia em primeiro lugar, por meio da técnica mais importante - a técnica virtualização. O sistema operacional interage com um recurso físico (processador, memória, disco, etc.) e o transforma em uma forma mais geral, mais poderosa e mais fácil de usar. Portanto, para uma compreensão geral, você pode comparar aproximadamente o sistema operacional com uma máquina virtual.

Para permitir que os usuários dêem comandos ao sistema operacional e, assim, usem os recursos da máquina virtual (como executar um programa, alocar memória, acessar um arquivo e assim por diante), o sistema operacional fornece uma interface chamada API (interface de programação do aplicativo) e para o qual você pode fazer chamadas (call). Um sistema operacional típico permite que centenas de chamadas de sistema sejam feitas.

Finalmente, uma vez que a virtualização permite que vários programas sejam executados (compartilhando assim a CPU) e acessem simultaneamente suas instruções e dados (compartilhando assim a memória) e acessem discos (compartilhando assim os dispositivos de E/S). ), o sistema operacional também é chamado de gerente de Recursos. Cada processador, disco e memória é um recurso do sistema, e assim uma das funções do sistema operacional passa a ser a tarefa de gerenciar esses recursos, fazendo-o de forma eficiente, honesta, ou vice-versa, dependendo da tarefa para a qual este sistema operacional é projetado.

virtualização de CPU

Considere o seguinte programa:
(https://www.youtube.com/watch?v=zDwT5fUcki4)

Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (tradução)

Ele não executa nenhuma ação especial, na verdade, tudo o que faz é chamar uma função girar(), cuja tarefa é percorrer a verificação de tempo e retornar após um segundo. Assim, ele repete indefinidamente a string que o usuário passou como argumento.

Vamos executar este programa e passar o caractere "A" como argumento. O resultado não é particularmente interessante - o sistema simplesmente executa um programa que exibe periodicamente o caractere "A".

Agora vamos tentar a opção quando muitas instâncias do mesmo programa estiverem rodando, mas gerando letras diferentes para deixar mais claro. Nesse caso, o resultado será um pouco diferente. Apesar de termos um processador, o programa é executado simultaneamente. Como isso acontece? Mas acontece que o sistema operacional, não sem a ajuda dos recursos de hardware, cria uma ilusão. A ilusão de que o sistema possui vários processadores virtuais, transformando um único processador físico em um número teoricamente infinito e, assim, permitindo que aparentemente programas sejam executados simultaneamente. Essa ilusão é chamada virtualização de CPU.

Essa imagem levanta muitas questões, por exemplo, se vários programas quiserem rodar ao mesmo tempo, qual deles será lançado? As “políticas” do SO são as responsáveis ​​por essa questão. As políticas são usadas em muitos lugares no sistema operacional e respondem a perguntas como esta, e são os mecanismos básicos que o sistema operacional implementa. Daí o papel do sistema operacional como gerenciador de recursos.

Virtualização de memória

Agora vamos olhar para a memória. O modelo físico de memória em sistemas modernos é representado como uma matriz de bytes.. Para ler da memória, você precisa especificar endereço de celularpara acessá-lo. Para gravar ou atualizar dados, você também deve especificar os dados e o endereço da célula onde gravá-los.

A memória é acessada constantemente durante a execução do programa. Um programa armazena toda a sua estrutura de dados na memória e a acessa executando várias instruções. As instruções, por sua vez, também são armazenadas na memória, portanto ela também é acessada a cada requisição da próxima instrução.

chamada malloc()

Considere o seguinte programa, que aloca uma região de memória usando a chamada malloc () (https://youtu.be/jnlKRnoT1m0):

Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (tradução)

O programa faz várias coisas. Primeiro, ele aloca alguma memória (linha 7), depois imprime o endereço da célula alocada (linha 9), grava zero no primeiro slot da memória alocada. Em seguida, o programa entra em um loop no qual incrementa o valor armazenado na memória no endereço da variável “p”. Ele também imprime o próprio ID do processo. O ID do processo é exclusivo para cada processo em execução. Depois de lançar várias cópias, nos depararemos com um resultado interessante: no primeiro caso, se você não fizer nada e apenas executar várias cópias, os endereços serão diferentes. Mas isso não se enquadra na nossa teoria! Correto, já que as distribuições modernas têm a randomização de memória habilitada por padrão. Se estiver desabilitado, obtemos o resultado esperado - os endereços de memória de dois programas em execução simultânea serão correspondentes.

Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (tradução)

Como resultado, dois programas independentes funcionam com seus próprios espaços de endereço privados, que por sua vez são mapeados pelo sistema operacional na memória física. Portanto, o uso de endereços de memória dentro de um programa não afetará os outros de forma alguma, e parece a cada programa que ele possui seu próprio pedaço de memória física, inteiramente dado a ele. A realidade, entretanto, é que a memória física é um recurso compartilhado gerenciado pelo sistema operacional.

Consistência

Outro dos tópicos importantes dentro dos sistemas operacionais é - consistência. Este termo é usado quando se fala de problemas no sistema que podem ocorrer ao trabalhar com muitas coisas ao mesmo tempo dentro do mesmo programa. Problemas de consistência surgem até mesmo dentro do próprio sistema operacional. Nos exemplos anteriores de virtualização de memória e processador, percebemos que o sistema operacional gerencia muitas coisas ao mesmo tempo - ele inicia o primeiro processo, depois o segundo e assim por diante. Como se viu, esse comportamento pode levar a alguns problemas. Assim, por exemplo, os programas multithread modernos enfrentam essas dificuldades.

Considere o seguinte programa:

Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (tradução)

O programa na função principal cria dois threads usando a chamada pthread_create(). Neste exemplo, um thread pode ser pensado como uma função sendo executada no mesmo espaço de memória ao lado de outras funções, com claramente mais de uma função sendo executada ao mesmo tempo. Neste exemplo, cada thread inicia e executa a função worker() que por sua vez simplesmente incrementa a variável,.

Vamos executar este programa com um argumento de 1000. Como você deve ter adivinhado, o resultado deve ser 2000 porque cada thread incrementa a variável 1000 vezes. No entanto, nem tudo é tão simples. Vamos tentar executar o programa com uma ordem de grandeza a mais de repetições.

Sistemas Operacionais: Três Peças Fáceis. Parte 1: Introdução (tradução)

Ao inserir um número, por exemplo, 100000, esperamos ver a saída como o número 200000. No entanto, se executarmos o número 100000 várias vezes, não apenas não veremos a resposta correta, mas também obteremos diferentes respostas incorretas. A resposta está no fato de que, para aumentar o número, são necessárias três operações - extrair o número da memória, incrementá-lo e, em seguida, escrever o número de volta. Como todas essas instruções não são executadas atomicamente (todas ao mesmo tempo), coisas estranhas como essa podem acontecer. Este problema é chamado em programação condição de corrida. Quando forças desconhecidas em um momento desconhecido podem afetar o desempenho de qualquer uma de suas operações.

Fonte: habr.com

Adicionar um comentário