Prévia do material em texto
Automação em Tempo Real Processos e Threads André Paim Lemos andrepaim@ufmg.br UNIVERSIDADE FEDERAL DE MINAS GERAIS DEPARTAMENTO DE ENGENHARIA ELETRÔNICA Mo#vação • Primeiros sistemas operacionais (S.O.) – Monotarefa – Apenas um progama era executado • Programa tomava o controle do sistema e #nha acesso a todos os recursos do sistema Mo#vação • Sistemas operacionais modernos – Mul#tarefa • Múl#plos progamas carregados na memória e executando concorrentemente – S.O. deve ser capaz de controlar a execução de mú#plos programas – Criação do conceito do processo • Programa em execução + estado da execução • Unidade de trabalho em um sistema de compar#lhamento de tempo Mo#vação • Sistema operacional formado por uma coleção de processos: – Processos do sistema operacional – Processos do usuário • Todos esses processos podem ser executados concorrentemente em uma única CPU através do compar#lhamento de tempo de processamento Mo#vação Processo • Um processo é um fluxo de controle sequencial e seu espaço de endereçamento *stack_overflow.cpp Processo • Vários processos podem estar executando concorrentemente criados a par#r do mesmo programa – Ex: dois usuários u#lizando um processador de texto no mesmo computador • Um programa pode criar vários processos – Ex: Google Chrome Estados de um Processo • Durante a existência de um processo, este pode assumir geralmente três estados*: – Executando (running): instruções estão sendo executadas – Bloqueado (blocked): esperando por algum evento (E/S, recepção de alguma sinal, etc.) – Pronto (ready): pronto para usar a CPU * Número de estados e nomenclatura varia dependendo do S.O. Estados de um Processo • A cada instante – Apenas 1 processo econtra-‐se no estado executando – Vários processos podem estar bloqueados ou prontos • Sistema operacional mantêm: – Uma fila de processos prontos ordenada pela prioridade – Uma (ou mais) fila(s) de processos bloqueados Estados de um Processo • Durante a criação do processo, seu estado inicial é definido como new Estados de um Processo • Depois de criado, caso existam outros processos executando, seu estado é definido como ready Estados de um Processo • Processo aguarda na fila de processos prontos até que chegue ao topo da fila – Estado: ready-‐> running Estados de um Processo • Processo executa por um determinado tempo (quatum), quando o tempo termina o S.O. interrompe sua execução* – Estado: running -‐> ready * Sistemas operacionais preempe#vos Estados de um Processo • As transições entre running e ready são executadas pelo escalonador de processos (parte do S.O.) • O processo não tem conhecimento dessas transições (mul#tarefa preempi#va) Estados de um Processo • Caso processo esteja executando e necessite esperar por um evento de E/S (entrada de dados do usuário no teclado, escrita no disco, etc.) – Estado: running -‐> waiDng *E/S = Entrada e saída Estados de um Processo • Ao término da operação de E/S, o processo bloqueado volta à fila dos prontos – Estado: waiDng-‐> ready Estados de um Processo • Quando o processo termina sua execução – Estado: running-‐> terminated Implementação de um Processo • Para implementar um processo o S.O. mantêm uma tabela de processos – Uma entrada por processo • Cada entrada da tabela contêm informações sobre o estado do processo – Cada entrada é comumente definida como um Process Control Block (PCB) Process Control Block • Estado do processo • Program counter – a próxima instrução a ser executada • Registradores – acumulador, stack pointer, etc. • Informação para escalonamento – prioridade, ponteiro para fila de escalonamento, etc • Informação de gerenciamento de memória • Estads#cas – tempo de CPU, tempo real de execução • Estado de E/S – lista de arquivos abertos, disposi#vos de E/S alocados ao processo , etc Filas de Processos • Todos os processos presentes na memória com estado ready são armazenados em uma fila de processos prontos (ready queue) • Processos com estado waiDng são armazenados em filas de esperas, como por exemplo, filas de disposiDvos (device queue) Filas de Processos • Uma forma de representar a dinâmica dos processos no S.O. é através e um diagrama de filas Chaveamento de Contexto • Nas transições: running -‐> ready|waiDng ocorre chaveamento de contexto. • O S.O.: – Salva todos os registradores de uso geral da CPU – Salva registradores de endereçamento (program counter, stack pointer, etc.) – Salva uma imagem da área de dados e de pilha do processo • Informações são salvas no Process Control Block (PCB) do processo a ser interrompido Chaveamento de Contexto • Na transição ready -‐> running o S.O. restaura as informações armazenadas no PCB Operações em Processos • Um S.O. mul#tarefa deve permi#r a realização de diversas tarefas relacionadasa processsos, tais como: – Criar um processo – Destruir um processo – Bloquear um processo – Suspender/con#nuar um processo – Mudar prioridade de um processo • Criar um processo envolve muitas operações, tais como: – Iden#ficar o processo (PID = Proccess IdenDfier) – Criar o PCB do processo – Alocar recursos iniciais para o processo (exemplo: RAM) – Inserir o processo na lista dos prontos Criação de Processos • Um processo pode criar um novo processo – Chamada de sistema para criar um processo • O processo que cria é chamado de pai (parent) • Os novos processos de filhos (children) • Geralmente os S.O. iden#ficam os processos usando um iden#ficador único de processo – Process IdenDfier (PID) Criação de Processos • Árvore de processos dpica do S.O. Solaris Criação de Processos • Código em C para linux, criação de um processo filho *fork_test.c Escalonamento de Processos • O obje#vo de um S.O. mul#tarefa é ter sempre um processo executando, para maximizar a u#lização da CPU Escalonamento de Processos • Tempo dpico de u#lização da CPU Escalonamento de Processos • Toda vez que a CPU fica ociosa, o S.O. deve selecionar outro processo para executar • Essa operação é realizada pelo escalonador de processos • A fila de processos prontos (ready queue) não é necessariamente FIFO (first in first out) – Fila de prioridades = prioridade de cada processo Escalonamento de Processos • Decisões de escalonamento devem ocorrer: – Running -‐> wai#ng -‐ requisição de E/S – Running -‐> ready -‐ interrupção – Wai#ng -‐> ready -‐ término de operação de E/S – Running -‐> terminated -‐ fim de execução Escalonamento de Processos • Existem diversas estratégias de escalonamento de processos • Quando um processo em execução pode ser interrompido pelo S.O. (por exemplo, depois que seu Dme-‐slice termine) o escalonamento é dito preemp#vo – Caso contrário, o escalonamento é não-‐preemp#vo Escalonamento de Processos • No escalonamento preemp#vo – O S.O. interrompe a execução do processo a#vo e despacha um novo processo para execução – O S.O. u#liza um relógio de hardware (real-‐Dme clock RTC), que periodicamente gera interrupções que, por sua vez, devolvem o controle da CPU ao S.O. • No escalonamento não-‐preemp#vo, o processo executa até que encerre sua execução ou libere a CPU de forma espontânea (ex: requisição E/S) Escalonamento de Processos • Em sistemas de tempo real o escalonamento preemp#vo é o mais u#lizado – Garante que processos com maior prioridade tenham chance de atender seus requisitos de tempo • Estratégias de escalonamento de tempo real serão vistas futuramente Escalonamento de Processos Threads • Um dos componentes do processo é a sequência de instruções (código) a ser executada – Essa sequência é definida como linha de execução (thread) primária – Em um programa em C a thread primária executa o código presente na função main() • Sistemas operacionais modernos permitem que um mesmo processo tenha várias linhas de execução independentes (mulDthread) executando concorrentemente Threads – Mo#vação • Dado um sistema que possua interface com usuário e realize um processamento periódico – Exemplo: SomPLC • Caso o programa seja feito em uma única thread, a interface com o usuário não será responsiva durante o processamento • Solução: usar uma (ou mais) threads auxiliares para realizar o processamento Threads – Mo#vação • CLP = usar uma thread por funcionalidade Thread • Thread = processo “leve” (lightweigth process) – Compar#lham recursos do processo que as originou Threads Threads • Criação de 50000 processos ou threads em diferentes arquiteturas Platform fork() pthread_create() real user sys real user sys Intel 2.8 GHz Xeon 5660 (12cpus/node) 4.4 0.4 4.3 0.7 0.2 0.5 AMD 2.3 GHz Opteron (16cpus/node) 12.5 1.0 12.5 1.2 0.2 1.3 AMD 2.4 GHz Opteron (8cpus/node) 17.6 2.2 15.7 1.4 0.3 1.3 IBM 4.0 GHz POWER6 (8cpus/node) 9.5 0.6 8.8 1.6 0.1 0.4 IBM 1.9 GHz POWER5 p5-‐575 (8cpus/node) 64.2 30.7 27.6 1.7 0.6 1.1 IBM 1.5 GHz POWER4 (8cpus/node) 104.5 48.6 47.2 2.1 1.0 1.5 INTEL 2.4 GHz Xeon (2 cpus/node) 54.9 1.5 20.8 1.6 0.7 0.9 INTEL 1.4 GHz Itanium2 (4 cpus/node) 54.5 1.1 22.2 2.0 1.2 0.6 Threads • Vantagens – Múl#plas threads de um processo compar#lham o mesmo espaço de endereçamento – Mais fáceis de criar, escalonar e destruir que processos – Úteis em sistemas com múl#plas CPU permi#ndo desenvolvimento de aplicações paraleas Modelos de Threads • Threads de usuário (user threads) – Definidas sem suporte do kernel • Threads de kernel (kernel threads) – Definidas com suporte do S.O. – Todos os sistemas operacionais modernos suportam threads de kernel Modelos de Threads Threads em C++ • O desenvolvimento de programas mul#thread em C++depende de mecanismos capazes de: – Criar e encerrar threads – Realizar operações sobre threads – Sincronizar a comunicação entre threads • Até 2011, a linguagem C++ não oferecia uma biblioteca padrão para desenvolvimento de aplicações mul#thread • Os desenvolvedores u#lizavam: – API específicas disponibilizadas por S.O. (Win32 API, POSIX Threads) • Geralmente escritas em C – Ou, bibliotecas em C++ que encapsulam essas APIs • Boost, Qt, etc. Threads em C++ • Em 2011 um novo padrão da linguagem C++ foi definido – C++11 -‐ ISO/IEC 14882:2011 – Inclui várias adições para a linguagem e algumas bibliotecas – Entre as bibliotecas, uma biblioteca de threads • Headers <thread>, <mutex>, <condi#on_variable>, etc. Threads em C++ • Vantagens de se usar a biblioteca padrão – Biblioteca em C++ padronizada – Todos os compiladores eventualmente irão implementar a biblioteca de threads • As versões mais recentes de vários compiladores C++ incluem a biblioteca de threads – Mul#plataforma • Código roda em diferentes S.O. sem modificações C++11 -‐ Thread C++11 – Criação de Threads Ver exemplos create_thread.cpp thread_shared_var.cpp C++11 -‐ Encerramento • Uma thread termina se – A thread termina a execução de sua função principal – O processo ao qual a thread pertence é terminado Threads -‐ Término • Uma thread pode esperar o término de outra C++11 – Criação de Threads Ver exemplo thread_vector.cpp C++11 -‐ Threads • Uma thread é “joinable” se outras threads podem esperar pelo seu término usando o método join() • Se a thread é “detached” outras threads não podem aguardar seu término • Por default, as threads são criadas como “joinable” – Para definir uma thread como “detached” u#liza-‐ se o método detach() C++11 -‐ Threads • O método detach() separa a execução da thread do objeto do #po std::thread associado • Permite que a thread con#nue executando mesmo se o objeto associado seja destruído • Ú#l quando é necessário criar várias threads em uma função, mas não é necessário (ou possível) armazenar os objetos correspondentes e esperar pelo término de todas as threads C++11 – Threads -‐ Detached Compiladores compadveis com C++11 • Alguns compiladores que implementam a biblioteca de threads do padrão C++11 – Microsom Visual C++ >= 2012 • Windows – gcc (versão > 4.7) • Linux, MacOSX, etc C++11 -‐ Threads • Referência da API hYp://en.cppreference.com/w/cpp/thread Boost • Como proceder caso a versão do compilador não inclua a biblioteca de threads do padrão C++11 • Biblioteca Boost (hYp://www.boost.org) – Conjunto de bibliotecas em C++ para threads, expressão regular, comunicação via rede, entre outras – A API da bilioteca de threads C++11 e boost é pra#camente a mesma • Boost serviu de inspiração para a padronização • Salvas poucas excessões, basta alterar o namespace e o arquivo de cabeçalho – #include <thread> => #include <boost/thread/thread.hpp> – std::thread => boost::thread