Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
so:preempcao_por_tempo [2016/11/24 15:32] – maziero | so:preempcao_por_tempo [2023/03/29 16:11] (atual) – [Condições de disputa] maziero | ||
---|---|---|---|
Linha 1: | Linha 1: | ||
+ | ====== Preempção e compartilhamento de tempo ====== | ||
+ | |||
+ | :!: alterações na interface em 03/ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | Até agora, nosso sistema suporta apenas tarefas cooperativas. O objetivo deste projeto é adicionar preempção por tempo ao sistema. Com essa modificação, | ||
+ | |||
+ | ===== Preempção ===== | ||
+ | |||
+ | Em sistemas de tempo compartilhado (// | ||
+ | |||
+ | Em um sistema real, a implementação da preempção por tempo tem como base as interrupções geradas pelo temporizador programável do hardware. Esse temporizador é programado para gerar uma interrupção a cada 1 milissegundo, | ||
+ | |||
+ | Quando uma tarefa recebe o processador, | ||
+ | |||
+ | {{ time-sharing.png |Compartilhamento de tempo}} | ||
+ | |||
+ | Como um processo UNIX não tem acesso direto aos temporizadores e interrupções do hardware, vamos simular o temporizador de hardware usando um temporizador UNIX, e o mecanismo de interrupção será simulado através de //sinais UNIX//, que serão explicados a seguir. | ||
+ | |||
+ | ===== Sinais UNIX ===== | ||
+ | |||
+ | O mecanismo de sinais do UNIX é similar às interrupções (IRQs) geradas pelo hardware: ao receber um sinal, um processo desvia sua execução para uma função que ele previamente registrou no sistema operacional. | ||
+ | |||
+ | A página de manual '' | ||
+ | |||
+ | Um exemplo do uso de sinais está no arquivo '' | ||
+ | |||
+ | ===== Temporizadores UNIX ===== | ||
+ | |||
+ | Para simular as interrupções de relógio do hardware, faremos uso do mecanismo de sinais (para implementar a preempção) e de temporizadores UNIX (para gerar os //ticks// de relógio). O UNIX permite definir temporizadores através das chamadas de sistema '' | ||
+ | |||
+ | ===== Implementação ===== | ||
+ | |||
+ | O mecanismo a ser implementado pode ser resumido nos seguintes passos: | ||
+ | |||
+ | - Durante a inicialização do sistema, um temporizador deve ser programado para disparar a cada 1 milissegundo; | ||
+ | - Os disparos do temporizador devem ser tratados por uma rotina de tratamento de //ticks//; | ||
+ | - ao ganhar o processador, | ||
+ | - ao ser acionada, a rotina de tratamento de //ticks// de relógio deve decrementar o contador de quantum da tarefa corrente, se for uma tarefa de usuário; | ||
+ | - se o contador de quantum chegar a zero, a tarefa em execução deve voltar à fila de prontas e o controle do processador deve ser devolvido ao // | ||
+ | |||
+ | Sua implementação deve funcionar com {{pingpong-preempcao.c|este código}} e deve gerar um resultado similar ao {{pingpong-preempcao.txt|desta saída}}. Um teste de //stress//, para verificar se seu sistema se comporta bem com muitas tarefas, também está disponível: | ||
+ | |||
+ | <note warning> | ||
+ | A rotina de tratamento de //ticks// de relógio é **crítica**, | ||
+ | </ | ||
+ | |||
+ | ===== Condições de disputa ===== | ||
+ | |||
+ | É importante evitar preempções dentro do // | ||
+ | |||
+ | * Tarefas críticas como o // | ||
+ | * As demais tarefas (//Main//, //Pang//, ...// | ||
+ | * O tratador do temporizador deve sempre verificar se a tarefa corrente é de usuário ou de sistema, antes de preemptá-la devido ao fim de um // | ||
+ | |||
+ | Uma solução mais " | ||
+ | |||
+ | Versões mais antigas do núcleo Linux possuíam uma trava global chamada // | ||
+ | |||
+ | ===== Outras informações ===== | ||
+ | |||
+ | * Duração estimada: 4 horas. | ||
+ | * Dependências: | ||
+ | * [[Gestão de Tarefas]] | ||
+ | * [[Dispatcher]] | ||