Sistemas Operativos - Processos e Threads

15
Sistemas Operativos Apontamentos sobre Processos e Threads Cap. 3 - Processos: O que é um processo ? Um processo é como que um contentor/ambiente onde existe um conjunto de recursos que são usados por parte do programa a ser execudado dentro do ambiente. Fornece a noção de que o programa é a unica execução activa e tem todo o acesso aos recursos do computador. O principal recurso de um processo é o espaço de endereçamento virtual. O que identifica um processo ? Um processo pode ser identificado por diversos parâmetros, entre eles os seguintes: Identificador: Um identificador único associado ao processo de forma a poder distinguir dos restantes. Estado: Estado actual depende de certos factores. Prioridade: Nivel de prioridade relativamente a outros processos. Program Counter: O endereço da próxima instrucção a ser executada no programa. Ponteiros para Memória: Inclui ponteiros para o código do programa e dados associados ao programa. Dados de Contexto: Dados presentes nos registos do CPU enquano o processo está a ser executado.

description

Apontamentos pessoais acerca de sistemas operativos, mais concretamente, acerca de Processos e Threads. Erros ortográficos existentes, pelo que se sugere que se ignorem os mesmos.

Transcript of Sistemas Operativos - Processos e Threads

Page 1: Sistemas Operativos - Processos e Threads

Sistemas OperativosApontamentos sobre Processos e Threads

Cap. 3 - Processos:

O que é um processo ?

Um processo é como que um contentor/ambiente onde existe um conjunto de recursos quesão usados por parte do programa a ser execudado dentro do ambiente. Fornece a noção de que oprograma é a unica execução activa e tem todo o acesso aos recursos do computador. O principalrecurso de um processo é o espaço de endereçamento virtual.

O que identifica um processo ?

Um processo pode ser identificado por diversos parâmetros, entre eles os seguintes:

• Identificador: Um identificador único associado ao processo de forma a poder distinguir dos restantes.

• Estado: Estado actual depende de certos factores.

• Prioridade: Nivel de prioridade relativamente a outros processos.

• Program Counter: O endereço da próxima instrucção a ser executada no programa.

• Ponteiros para Memória: Inclui ponteiros para o código do programa e dados associados ao programa.

• Dados de Contexto: Dados presentes nos registos do CPU enquano o processo está a ser executado.

Page 2: Sistemas Operativos - Processos e Threads

Possiveis Estados de um Processo:

• New: O processo está no estágio de criação;

• Ready: O processo tem agora disponivel todos os recursos de que necessita para ser executado, porém o CPU não está a executar as instrucções que este processo contém;

• Running: The CPU está a executar as instrucções que este processo contém;

• Waiting: O processo não pode continuar a ser executado devido a estar à espera de algum recurso ou que algum event ocorra.

• Terminated: O processo foi executado por completo;

Representação de um Processo em Linux:

Tipicamente, a estrutura que representa um processo em linux é a struct task_struct. Estaestrutura contém toda a informação necessária para representar um processo.

Estesdados são guardados acerca de cada processo criado, e assim, é possivel interromper o fluxode execução, realizar outro tipo de trabalho e retomar o trabalho neste processo anterior poistodos os dados do contexto actual foram guardados numa estrutura de dados. Tipicamente,tem o nome de Process Control Block.

Illustration 1: Diversos estados de um processo;

Struct task_struct{pid_t pid; //process identifierlong state; //state of the processunsigned int time_slice; //scheduling informationstruct task_struct *parent; //this process's parentstruct list_head children; //this process's childrenstruct files_struct *files; //list of open filesstruct mm_struct *mm; //address space of this process

}

Page 3: Sistemas Operativos - Processos e Threads

Como é que um processo passa de inactivo a activo?

Tipicamente, o OS vai à tabela de processos, obtém os dados acerca desse mesmo e carrega nosregistos do CPU os dados relativos ao seu contexto armazenado, nomeadamente, o ProgramCounter e os dados associados ao código do programa.

Acções necessárias para 'matar' um processo:

• Terá de terminar todas as threads activas;

• Libertar a memória usada para definir o espaço de endereçamento;

Pros e Contras da existência de Processos:

O modelo que especifica trocas de informação entre processos é muito simples: File Tables sãopartilhadas e espaços de endereçamento não são. Esta separação dos espaços de endereçamento temvantagens e desvantagens. Desde logo, é evidente que um processo não pode escrever noutro espaçode endereços que não seja o seu, o que elimina diversos problemas. Por outro lado, processos comespaço de endereços diferente dificulta a comunicação entre eles. Para que esta comunicação sejaestabelecida, tem de ser feita através de mecanismos IPC (inter-process comunication). O própriocontrolo via tabelas de processos e este uso de IPC's causa um grande overhead.

Espaço Privado de Endereços:

Um processo fornece a cada programa a ilusão de que tem acesso exclusivo ao espaço de endereços do sistema. Numa máquina com endereços de n-bit, o espaço de endereços é um conjuntopossivel de 2n. Este espaço é privado na medida em que um qualquer endereço pertencente a esse mesmo espaço não pode ser lido ou escrito por outros processos.

A parte mais no topo, Kernel Virtual Memory contém os dados, stack e código que é executado porparte parte do Kernel em nome do processo.Tipicamente, acontece quando são utilizadas SystemCalls por parte do programa.

Illustration 2: Mapa de espaços de endereços fornecido a um qualquer processo;

Page 4: Sistemas Operativos - Processos e Threads

Modo User e Kernel :

Tipicamente, um programa não pode executar qualquer tipo de instrução que o CPU fornece como sendo o seu instruction set. O processador fornece, portanto, um mecanismo que restringe o acesso que um programa tem relativamente ao conjunto de instruções, bem como regiões do espaço de endereçamento. Por programa, está implicito processo.

Tipicamente, exite um controlo através de um mode bit presente num registo de controlo que caracteriza os privilégios que o processo poderá ter relativamente ao sistema. Quando o mode bit está activo, o processo está a correr em Kernel Mode. Este é o modo mais previligiado. O processo pode "executar" qualquer instrucção do instruction set e aceder a qualquer região do espaço de endereçamento.

Por outro lado, quando o mode bit não está activo, o processo está a correr em user mode. Neste modo, o processo não tem total acesso como em kernel mode.

Por omissão, um processo começa por estar em modo user. A única maneira de obter uma mudança para kernel mode é através uma exception.

Exception:

• Interrupt:

• Traps:

• Fault:

Quando a exception acontece, o controlo passa para o exception handler, e isso mudaautomáticamente o modo associado com o processo porque o handler corre em kernel mode. Apósisso, quando o controlo é devolvido, o processo volta a obter o modo de user.

Page 5: Sistemas Operativos - Processos e Threads

Controlo sobre Processos:

Os sistemas baseados em Unix fornecem um conjunto de system calls para poder manipular processos dentro de programas em linguagem C.

Obter ID's de processos:

Cada processo, como pudemos ver anteriormente (task_struct), contém um identificadorpositivo. A system call getpid retorna o id do processo que invocou a chamada.

#include <sys/types.h>

#include <unistd.h>

//é a mesma coisa que retornar int

pid_t getpid(void);

pid_t getppid(void);

Returns: PID of either the caller or the parent

Criar e Terminar Processos:

Do ponto de vista do programador, podemos pensar num processo como estado num de trêsestados:

• Running: O processo está em execução por parte do CPU ou está à espera de serexecutado.

• Stopped: A execução do processo está suspensa e não será 'scheduled'/agendado.Um processo pára quando recebe um dos seguintes sinais – SIGSTOP, SIGTSTP,SIGTTIN, SIGTTOU – e permanece parado até receber o sinal SIGCONT, a partirdo qual pode ser de novo executado.

• Terminated: O processo está parado permanentemente. Pode acontecer por uma de três razões:

1. Recebeu um sinal que tem como intenção terminar o processo.

2. Retornou a partir da rotina main.

3. Invocou a função exit.

#include <stdlib.h>

void exit(int status);

This function does not return

Page 6: Sistemas Operativos - Processos e Threads

Um processo (parent) cria um novo processo (child) através da função fork.

#include <sys/types.h>

#include <unistd.h>

pid_t fork(void);

Returns: 0 to child, PID of child to parent, 1 on error−

O processo filho é muito parecido com o processo parent. O child recebe uma cópia (mas é algoseparado) do espaço de endereçamento vindo do parent. O child também recebe uma cópia da FileTable, ou seja, também tem acesso e privilégios para ler e escrever sobre os ficheiros que o processoparent tinha acesso. A principal diferença está no identificador PID.

A função fork é chamada uma vez e retorna duas vezes. Um retorno é para o processo parent edevolve o PID do processo child. O segundo retorno é para o processo child e devolve 0.

Ambos os processos fazem print no stdout porque tanto o processo child como o parent têm acessoaos ficheiros abertos, pelo que têm acesso ao stdout.

#include "csapp.h"

int main(){

pid_t pid;

nt x = 1;

pid = Fork();

if (pid == 0) { /* Child */

printf("child : x=%d\n", ++x);

exit(0);

}

/* Parent */

printf("parent: x=%d\n", --x);

exit(0);

}

Page 7: Sistemas Operativos - Processos e Threads
Page 8: Sistemas Operativos - Processos e Threads

Context Switches:

O kernel do sistema operativo implementa o mecanismos de multitasking como uma forma de controlo de exceptions de alto nivel – Context Switch.

O kernel mantém um context para cada processo. O contexto é o estado do processo (o que o caracteriza num determinado momento) que o kernel necessita de saber/armazenar de forma a resumir um processo interrompido anteriormente.

Tipicamente, o contexto contém o ultimo valor obtido por parte do program counter, a parte activada stack (user mode), a stack do kernel, entre outros. É também preciso restaurar estruturas dedados presentes na região do kernel, como por exemplo:

• Page Table - que caracteriza o espaço de endereçamento;

• Process Table – contém informação acerca do processo currente;

• File Table – contém informação acerca de ficheiros que o processo acedeu;

Durante a execução de um processo, o kernel pode decidir interromper o processo actualmente emexecução e resumir um processo anteriormente interrompido – scheduling – e é controlado por umpedaço de código pertencente à região do kernel chamadao de scheduler.

Como funciona o processo de context-switch:

1. Armazena o estado do processo actualmente em execução;

2. Restaura o estado previamente armazenado relativamente a um processointerrompido anteriormente;

3. Passa o controlo para o processo que acabou de ser restaurado;

Illustration 3: Exemplo de mudança de contexto;

Page 9: Sistemas Operativos - Processos e Threads

Carregar e Executar Programas:

A função execve carrega e executa um novo programa no contexto do processo currente.

#include <unistd.h>

int execve(const char *filename, const char *argv[], const char *envp[]);

Does not return if OK, returns 1 on error−

A função execve carrega e executa uma imagem executável passado por filename. A função só apresenta retorno caso seja encontrada uma excepção.

A lista de argumentos dada por argv e é representada por um array de ponteiros com cada indice a apontar para um dos argumentos.

Importante:

Após o execve carregar a imagem executável , invoca o código nativo de start. Esse código _start inicia a stack e passa controlo para a rotina main.

Tipica Organização da User Stack:

Page 10: Sistemas Operativos - Processos e Threads

Threads:

Threads são a virtualização do CPU. Consistem num identificador (thread ID), um Program Counter, uma Stack, e um restante conjunto de registos.

Processos MultiThread consistem em ter várias threads, vários fluxos de execução de um programa dentro de um mesmo processo. Essas threads têm acesso, em simultaneo, ao código do programa, aos dados por ele necessários e os ficheiros aos quais ele tem acesso. Em termos de registos e de stack, cada thread tem os seus.

O porquê de usarmos Threads:

• Muito úteis, na medida em que, um programa pode processar tarefas em simultâneo que de outra forma teriam de ser de forma sequencial, forma essa que acarreta com os seus devidos problemas.

• Um exemplo muito usual é o uso de threads num programa de editor de texto. Enquanto uma thread executa a tarefa de verificar erros ortográficos, outra thread poderá estar a carregar imagens do disco para o documento, e outro ainda poderá estar a criar backups do ficheiro de tempos a tempos.

Page 11: Sistemas Operativos - Processos e Threads

Vejamos o exemplo de um Web Server:

Ao usarmos o mecanismo de multi-threading na implementação de um web-server estamos apermitir que ele possa responder a vários requests em simultâneo. De outra forma, todas asrespostas teriam de ser dadas de forma sequêncial, ou pior, teriamos de multiplicar os processosassociados ao programa – causaria um grande overhead - o que faria com que o programa fossemais lento, tivesse um maior tempo de resposta associado a si. Tudo isto leva a um fracodesempenho.

Beneficios de Utilizar Threads:

• Melhor Resposta: Por exemplo, uma thread poderá ser responsável por dar uma resposta rápida a requests recebidos, enquanto outras executam por detrás de si, várias tarefas de cálculos exaustivos.

• Partilha de Recursos: Por omissão, threads partilham código do programa, dados associdosa este e outros recursos, que desta forma possibilitam que threads sejam executadas dentro do mesmo espaço de endereçamento.

• Economia de Recursos: Criar e gerir threads (context-switch) é muito mais rápido e barato do que implementar um programa que utilize replicação de processos.

• Programa Escaláveis (Scalability): Utilização de arquitecturas multiprocessador permite que um processo possa distribuir diversas tarefas do seu programa por tantas threads activas quantos processadores existirem.

Page 12: Sistemas Operativos - Processos e Threads

Modos de MultiThreading:

Threads podem ser incluidas em um de dois modos:

• Kernel Mode

• User Mode

Em implementações especificas, sejam de S.O. ou máquinas virtuais, tem de existir uma politica de mapeamento em torno de user threads e kernel threads.

Modo Muitos-para-Um:

Neste modo, muitas user-thread são mapeadas a uma única kernel-thread.

A principal dificuldade que este modelo tem é o facto de que, se for recebido um system callque bloquei um determinada thread, todo o processo irá ter bloqueado, mesmo que outrasthreads tenham a possiblidade de continuar a executar a sua tarefa.

Outra particularidade deste modelo é, como uma kernel-thread pode operar apenas numúnico CPU, este modelo não permite que um processo possa ser distribuido por multiplosCPU's.

Page 13: Sistemas Operativos - Processos e Threads

Modo Um-para-Um:

Como o nome indica, este modelo cria uma kernel-thread para cada user-thread.

Neste modelo não existem os problema apresentados no modelo anterior, por razões óbvias.

O grande problema deste modelo é o facto de que, como é criada uma kernel-thread paracada user-thread, vai acabar por existir um grande overhead devido à criação e manuntençãode tantas threads. O desempenho do sistema tende a diminuir com o aumento da criação dethreads. Tipicamente, sistemas que implementam este modelo também explicitam o númeromáximo de threads criadas.

Modo Muito-para-Muitos:

Este modelo implementa um combinação de várias user-threads com a mesma, oumenor, quantidade de kernel-threads. Não existe limite de criação de threads. Processos nãoficam bloqueados quando uma das threads recebe um system call de bloqueio, e é possiveldistribuir processos por vários CPU's.

Page 14: Sistemas Operativos - Processos e Threads

Bibliotecas de criação de Threads:

Tipicamente, cada linguagem de programação ou uma framework, fornece uma API especifica que ajuda programadores na criação de threads e na sua manuntenção. Três das mais conhecidas são:

1. Pthreads – Biblioteca que pode ser encontrada, por exemplo, na linguagem C;

2. Win32 Threads – Fornecidas com sistemas Windows ao nivel do kernel.

3. Java Threads – Como a linguagem Java corre sobre uma VM, tipicamente, a biblioteca de threads depende do S.O. e do hardware disponível.

Pthreads – Principais caracteristicas:

• Variáveis globais são partilhadas por todas as threads;

• Uma thread pode esperar que outras se juntem a si antes de continuar com a execução da sua tarefa;

• pThreas começam a sua execução numa função especificada (no exemplo, função runner);

Criação de pThreads:

Header necessário: #include <pthread.h>

Criação e 'wait' de pThreads:

main(){ pthread_t thread1, thread2; char *message1 = "Thread 1"; char *message2 = "Thread 2"; int iret1, iret2;

/* Create independent threads each of which will execute function */ iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1); iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);

/* Wait till threads are complete before main continues. Unless we */ /* wait we run the risk of executing an exit which will terminate */ /* the process and all threads before the threads have completed. */ pthread_join( thread1, NULL); pthread_join( thread2, NULL);

printf("Thread 1 returns: %d\n",iret1); printf("Thread 2 returns: %d\n",iret2); exit(0);}

Page 15: Sistemas Operativos - Processos e Threads

Win32 Threads:

Muito parecidas com as pThreads, porém, como todas as criações da microsoft, a nomemclatura é a maior diferença.

Java Threads:

Em Java, todos os programas usam threads. Mesmo até um programa como 'Hello World' – Main Thread.

O processo de criação de threads necessita de iniciar com um objecto que implemente a interface Runnable ou que uma class extends a class Thread. Desta forma, estará disponivel o hook method run que deve ser re-escrito de forma a fornecer funcionalidades à thread.

Criar um objecto Thread não faz com que a mesma seja executada. Uma thread é executada quando o método start é invocado. Este aloca toda a memória necessária e invoca o método run.

Em Java não existe o conceito de variáveis globais pelo que uma thread recebe, muitas vezes como parâmetro, objecto que será 'partilhado'.

Cancelamento de Threads:

Tipicamente, threads podem ser canceladas de duas maneiras:

• Asynchronous Cancellation : A thread é cancelada imediatamente;

• Deferred Cancelation: Activa uma flag que indica à thread que esta deve-se cancelar quando for conveniente. A flag que será cancelada terá de especificar como lidar com o sinal.

Cancelamente em AC pode ser prejudicial para dados partilhados e recursos alocados.

public static void main(String[] args){

....

Sum sumObject = new Sum();

Thread thr = new Thread(new ImplementsRunn(sumObject));

thr.start();

try{

thr.join();

System.out.print("The sum is"+ sumObject.getSum());

}catch(Exc.. e){

....

}

}