# Multitarefa

Quando um sistema operacional permite a execução de mais de um programa ao mesmo tempo, ele é chamado de multitarefa e tem de lidar com procedimentos que concorrem quanto à utilização da capacidade de processamento do hardware. Então, é necessário definir e gerenciar uma questão básica que é a prioridade de cada programa quanto ao uso de recursos existentes.
Os sistemas operacionais executam novos processos sem ter a necessidade que processos que foram iniciados antes precisem ser encerrados, para isso os programas executam segmentos (partes) de múltiplos processos de maneira intercalada fazendo que cada segmento dos processos executados, utilize os recursos computacionais (CPU, memória principal, disco, etc) de maneira ordenada e sequencial, mantendo as informações de cada processo consistentes.
A multitarefa automaticamente parcialmente interrompe a execução de cada processo salvando seu estado atual(resultados parciais, conteúdo de registradores, conteúdo de memória) e então carregando o estado salvo de outro processo e passando o controle dos recursos do sistema para ele, essa interrupção pode ser implementada a partir de divisões iguais de tempo (multitarefa preemptiva) ou administrada por um programa que gerencia e supervisiona os processos e define quando estes serão interrompidos.
A multitarefa não está diretamente ligada ao processamento paralelo pois mesmo em CPUs de vários núcleos, o processamento de mais de um processo é permitido em apenas um único núcleo do processador.

## História

O primeiro sistema informatizado a usar multitarefa foi o computador Leo 3, completado 1961.
A multitarefa preemptiva foi implementada nas versões iniciais do Unix em 1969, e é o padrão no Unix e em sistemas operacionais similares, incluindo Linux, Solaris e BSD em suas variações.
Pode parecer difícil de imaginar um computador monotarefa, i.e., que apenas permita utilizar uma aplicação mas, de fato, houve um percurso histórico notável até se atingir o nível atual de paralelização de processos. Com efeito, os primeiros computadores apenas permitiam executar uma única tarefa de cada vez. O Apple DOS é um excelente exemplo disso, já que foi dos primeiros sistemas operativos para computadores pessoais.
O primeiro passo para a multitarefa no MS-DOS foi a criação dos TSR's (Terminate and Stay Resident), pequenos programas que permaneciam em memória enquanto se executava outro programa, e que podiam instalar rotinas de tratamento de interrupções para serem ativados posteriormente. Ou seja, estando o utilizador a escrever um texto num processador de texto, por exemplo, poderia apertar uma combinação de teclas que dispararia uma interrupção e chamaria a TSR de uma agenda pessoal para tirar notas. Assim, do ponto de vista do processador, o processo do processador de texto era bloqueado e passava-se o controle para a agenda. Quando o utilizador terminasse, voltava-se ao processador. Ambos programas coexistiam, mas não podiam ser executados simultaneamente.
O passo seguinte foi a emulação de multitarefa. Exemplos disto eram as primeiras versões de Windows, que este executava sobre DOS (monotarefa), mas o núcleo do Windows fazia a sua própria gestão dos processos. Curiosamente, se um processo bloqueasse o Windows, todas as aplicações teriam que ser terminadas pois eram todas dependentes.
Posteriormente, surgiu uma das principais componentes dos SO atuais: o escalonador de processos, ou (em inglês) scheduler, que faria a gestão, qualificação e o gerenciamento de prioridade dos processos sem afetar o núcleo do sistema operativo. Ou seja, todas as tarefas núcleo são críticas, e todo o tempo que sobrar é legado aos processos. Adivinha-se, portanto, a necessidade de estabilizar o núcleo, por forma a minimizar o tempo de execução de tarefas internas.
O escalonador de processos é uma componente muito polêmico em termos de inovação e de aplicações. Dependendo das situações, um escalonador de processos deve gerir os seus processos por forma a diminuir a latência entre aplicações interativas, ou assegurar a coerência em termos de critérios no escalonamento: se uma tarefa não é crítica, então não devia estar a ser executada.

## Diferentes tipos de sistemas multitarefas

Os sistemas podem ainda ser classificados pela forma com que suas aplicações são gerenciadas, podendo ser divididos em sistemas batch, de tempo compartilhado ou de tempo real.
Um sistema operacional pode suportar um ou mais destes tipos de processamento, dependendo de sua implementação.
Sistemas batch: Foram os primeiros tipos de SOs multiprogramáveis a serem implementado. Eram armazenados em disco enquanto esperam para serem executados.
Sistemas de tempo compartilhado: Os sistemas de tempo compartilhado (timesharing) também são conhecidos por sistemas online. Permitem que diversos programas sejam executados a partir da divisão do tempo do processador em pequenos intervalos, denominados fatia de tempo (time-slice).
Sistemas de tempo real: Os sistemas de tempo real (real-time) são implementados de forma semelhante à dos sistemas de tempo compartilhado. A diferença entre os dois tipos de sistemas é o tempo exigido no processamento das aplicações. Em sistemas de tempo compartilhado o tempo de processamento pode variar sem comprometer as aplicações em execução. Em sistemas de tempo real os tempos de processamento devem estar dentro de limites rígidos (devem ser obedecidos) caso contrário poderão ocorrer problemas irreparáveis.

## Tarefas

Os conceitos ligados ao paralelismo de tarefas não são consensuais. A linguagem vulgar no UNIX sugere, no entanto, alguns termos razoavelmente universais.
No UNIX, existem dois níveis de tarefa: o processo e a thread. Os processos têm uma série de threads associadas. Tipicamente, cada processo tem um determinado espaço de endereçamento que as diferentes threads compartilham. Cada thread tem o seu próprio estado de processador e a sua própria pilha.

## Processo

Um processo pode ser visto como um conjunto de recursos utilizados por uma ou mais tarefas. Cada processo é isolado e como recursos são atribuídos aos processos, as tarefas fazem o uso deles através dos processos. Assim uma tarefa de um processo A não consegue acessar recursos de uma tarefa do processo B.
As tarefas de um mesmo processo podem trocar informações com facilidade, pois compartilham a mesma área de memória. No entanto, tarefas de processos distintos não conseguem essa comunicação facilmente, pois estão em áreas diferentes de memória. Esse problema é resolvido com chamadas de sistema do kernel que permitem a comunicação entre processos.

## Alternância de tarefas

Cada processador pode executar apenas um programa de cada vez. Por esta razão, a multitarefa num sistema uniprocessador (ou monoprocessador) é apenas uma ilusão conseguida com a alternância rápida entre as várias tarefas.
O núcleo do sistema operativo é responsável por isolar os contextos de execução das diversas tarefas. Para conseguir isto, é necessário que uma rotina do núcleo seja chamada a dada altura. Essa rotina (que pode ser chamada por uma interrupção provocada por um temporizador interno do computador) geralmente executa as seguintes operações:
* Salva o estado do processador numa estrutura de dados do núcleo (a árvore de processos);
* Seleciona, com base num algoritmo, a próxima tarefa a executar;
* Se for necessário, reconfigura o espaço de endereçamento de modo a que a próxima tarefa encontre a memória no estado que espera;
* Carrega o estado do processador referente à tarefa que vai receber tempo de processador;
* A rotina retorna permitindo que o programa execute.

## Escalonador

Para que a CPU não fique muito tempo sem executar tarefa alguma, os sistemas operacionais utilizam técnicas para escalonar os processos que estão em execução na máquina. O escalonamento é a atividade organizacional feita pelo escalonador da CPU, possibilitando executar os processos mais viáveis e concorrentes, priorizando determinados tipos de processos.
O Escalonador escolhe o processo que será executado pela CPU com o auxílio do hardware se preocupando com a eficiência da CPU e de maneira que execução dos processos seja realizada de maneira íntegra.
Os escalonadores preemptivos são algoritmos que permitem que um processo seja interrompido durante sua execução,tanto por uma interrupção de entrada/saída ou por decorrência do algoritmo de escalonamento adotado. Após a interrupção ocorre o que se chama de troca de contexto, que consiste em salvar o conteúdo dos registradores e a memória utilizada pelo processo que fora interrompido e conceder a outro processo o privilégio de executar na CPU restaurando os registradores e espaços de memória utilizado por esse processo.