Process management - Jorge Peixoto

24
Process Management 1 Process Management Process Management baseado na versão 2.6 do kernel do Linux Jorge Luiz Silva Peixoto [email protected] jorgepeixoto@{cos.ufrj.br, gmail.com} ESC / COPPE / UFRJ istemas Operacionais rof. Vitor Santos Costa, Ph.D.

Transcript of Process management - Jorge Peixoto

Page 1: Process management - Jorge Peixoto

Process Management 1

Process ManagementProcess Managementbaseado na versão 2.6 do kernel do Linux

Jorge Luiz Silva [email protected]@{cos.ufrj.br, gmail.com}

PESC / COPPE / UFRJSistemas OperacionaisProf. Vitor Santos Costa, Ph.D.

Page 2: Process management - Jorge Peixoto

Process Management2

Introdução e Motivação Introdução e Motivação O que é um processo?

Um programa em execução. É composto de:

Espaço deendereçamento

ThreadsKerneldata

Sinaispendentes

Estado

Arquivosabertos

PCPilha

Registradores

Page 3: Process management - Jorge Peixoto

Process Management3

Introdução e Motivação Introdução e Motivação Ciclo de vida do processo:

Reproduz (assexuadamente):exec() ou fork()

Nasce:fork() ou exec()

Cresce:faz_algo()

Morre:exit() ou

Sinal

Reclicla:wait()

Slab allocator

Page 4: Process management - Jorge Peixoto

Process Management4

ProgramaçãoProgramação Descritor de Processos Estados de Processos Contexto de Processo vs de

SistemaEspaço de Usuário vs de Sistema

Hierarquia de Processos Criação de Processos Copy-on-Write fork() copy_process()

vfork() Threads Threads – Implementação Kernel Threads Finalização de Processos do_exit() Remoção do Descritor de

Processos release_task() Processos Órfãos

Page 5: Process management - Jorge Peixoto

Process Management5

Descritor de ProcessosDescritor de Processos Em Linux:

task = process O kernel mantém os

processos numa lista circular duplamente encadeada chamada task list.

Cada elemento da lista é um process descriptor do tipo struct task_struct

Page 6: Process management - Jorge Peixoto

Process Management6

Descritor de ProcessosDescritor de Processos struct task_struct é alocado

dinamicamente via slab allocator que provê reuso de objetos e cache coloring. [cap. 11]

Antes do kernel 2.6, task_struct era alocado estaticamente no final da pilha de kernel de cada processo, dessa forma era possível calcular a localização da estrutura através do ponteira da pilha. O objetivo era economizar registradores.

Atualmente, um ponteiro é armazenado em struct thread_info que fica localizado na final da pilha.

Page 7: Process management - Jorge Peixoto

Process Management7

Descritor de ProcessosDescritor de Processos PID identifica unicamente um processo no sistema. PID é do tipo pid_t (tipicamente um int). Por questões de

compatibilidade o valor máximo é 32.768 (short int). O administrador por alterar esse valor em /proc/sys/kernel/pid_max

Processos são tipicamente referenciados por um ponteiro para seu task_struct, conseqüentemente, é interessante que o acesso seja rápido (implementado pelo macro current).

Sua implementação é dependente da arquitetura. No x86, o endereço da pilha de kernel do processo é usado calcular o endereço de thread_info que contém task_struct. No PowerPC, o valor é armazenado diretamente num registrador.

Page 8: Process management - Jorge Peixoto

Process Management8

Estados de ProcessosEstados de Processos TASK_RUNNING: processo ou está

rodando, ou está na fila esperando para rodar.

TASK_INTERRUPTIBLE: processo está dormindo (bloqueado) esperando por algum recurso. Muda para TASK_RUNNING, se for liberado o recurso ou receber um sinal.

TASK_UNINTERRUPTIBLE: idêntico ao anterior, exceto que o processo não acorda se receber um sinal.

TASK_ZOMBIE: o processo finalizou, mas seu pai ainda não chamou a system call wait().

TASK_STOPPED: a execução do processo está congelada; o processo não está executando nem é executável.

Page 9: Process management - Jorge Peixoto

Process Management9

Contexto de Processo Contexto de Processo vsvs de Sistema de SistemaEspaço de Usuário Espaço de Usuário vsvs de Sistema de Sistema Programas “normais”

executam em process context e em user mode.

Quando um programa “normal” chama uma syscall ou dispara uma exceção, ele entra em kernel mode.

Em system context, o kernel não está representando um processo, mas executando um interrupt handler.

Page 10: Process management - Jorge Peixoto

Process Management10

Hierarquia de ProcessosHierarquia de Processos

Todos os processos são filhos de init (PID 1).Na inicialização, o último passo do kernel é

chamar o init que chama o script inittab que conseqüentemente chama outros programas.

Todo processo tem apenas um pai, mas um pai pode ter zero ou mais processos filhos.

O relacionamento entre processos está registrado no descritor de processos.

É possível seguir na hierarquia de processos de qualquer processo para qualquer outro.

Page 11: Process management - Jorge Peixoto

Process Management11

Criação de ProcessosCriação de Processos A maioria dos sistemas

operacionais usa um mecanismo de spawn para criar um novo processo a partir de um outro executável.

No Unix, são usadas duas funções distintas: fork() e exec().

fork() cria um processo filho idêntico ao pai, exceto pelo PID, PPID, e alguns recursos, como: estatísticas do processo e sinais pendentes.

exec()carrega e executa um novo programa.

Outros SOs: fork() + exec()

if((result = fork()) == 0) { /* child code */ if(execve("new_program", ...) < 0) perror {"execve failed"); exit (1); } else if(result < 0) { perror("fork"); /* fork failed */ ) /* parent continues here */

Page 12: Process management - Jorge Peixoto

Process Management12

Copy-on-WriteCopy-on-Write Como alternativa a significante ineficiência do fork(),

no Linux, o fork() é implementado usando uma técnica chamada copy-on-write (COW).

Essa técnica atrasa ou evita a cópia dos dados. Ao invés de copiar o espaço de endereçamento do processo pai, ambos podem compartilha uma única cópia somente leitura. Se uma escrita é feita, uma duplicação é feita e cada processo recebe uma cópia. Conseqüentemente, a duplicação é feita apenas quando necessário, economizando tempo e espaço.

O único overhead realmente necessário do fork() é a duplicação da tabela de páginas do processo pai e a criação de um novo PID para o filho.

Page 13: Process management - Jorge Peixoto

Process Management13

fork()fork()

O Linux implementa fork() através da syscall clone() que recebe como entrada várias flags que especificam que recursos devem ser compartilhados.

fork() chama do_fork() que chama copy_process(), onde é feito a maior parte do trabalho.

Page 14: Process management - Jorge Peixoto

Process Management14

copy_process()copy_process() Chama dup_task_struct() que cria uma nova pilha de kernel, as estruturas

thread_info e task_struct. Os valores são iguais ao do processo pai. Checa se o novo filho não irá exceder os limites de recursos do usuário. Vários campos do descritor do processo são zerados ou atribuídos valores iniciais.

Dados estatísticos do processo não são herdados. A parte principal dos dados do descritor do processo é compartilhada.

Ao estado do processo filho é atribuído TASK_UNINTERRUPTIBLE. copy_process() chama copy_flags() para atualizar os flags de

task_struct. Chama get_pid() para atribuir o novo PID do processo filho. Dependendo dos flags passado à syscall clone(), copy_process() ou

duplica ou compartilha arquivos abertos, informações de sistema de arquivo, signal handlers, espaço de endereçamento e namespace. Esses recursos são tipicamente compartilhados entre threads.

Então, o restante de time slice é dividido entre o processo pai e o filho. Finalmente, copy_process() retorna para um ponteiro para o novo processo

filho.

Page 15: Process management - Jorge Peixoto

Process Management15

vfork()vfork()

Mesmo efeito do fork(), exceto por não copiar a tabela de páginas do processo pai.

Filho executa diretamente no espaço de endereçamento do pai.

Pai fica bloqueado até o filho chamar exec() ou sair. Não é permitido ao filho escrever no espaço de

endereçamento do processo pai. Otimização sugerida nos tempos de 3BSD. Hoje, com o copy-on-write, o único benefício é a não

cópia da tabela de páginas do processo pai.

Page 16: Process management - Jorge Peixoto

Process Management16

ThreadsThreads Em Linux, threads = processos Thread é meramente um processo que

compartilha recursos com outros processos. Abordagem diferente do Microsoft

Windows e do Sun Solaris que explicitamente têm suporte do kernel para threads (lightweight processes).

Exemplo: em Solares: existem 2 processos que consistem de 3 e 2 threads cada. Existirá um descritor de processos que aponta para cada conjunto de threads descrevendo os recursos compartilhados, como, o espaço de endereçamento e arquivos aberto. Cada thread então descreve os recursos que cada uma possui. Em Linux, simplesmente existe 5 processos e 5 estruturas task_struct. Os processos estão configurados para compartilhar certos recursos.

Page 17: Process management - Jorge Peixoto

Process Management17

Threads – ImplementaçãoThreads – Implementação Criados pela syscall clone(). Exemplo de chamada:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

Essa chamada criará uma thread que compartilha o espaço de endereçamento, recursos dos sistema de arquivos, descritores de arquivos e signal handlers.

Os flags passados para a syscall clone() descrevem o comportamento do processo filho e detalha os recursos compartilhados. Outros exemplo:fork() = clone(SIGHLD, 0);vfork() = clone(CLONE_VFORK | CLONE_VM | SIGHLD, 0);

Page 18: Process management - Jorge Peixoto

Process Management18

Kernel ThreadsKernel Threads

Kernel threads são processos que rodam apenas no espaço do kernel, não há mudança de contexto para o espaço de usuário.

Kernel threads não possuem espaço de endereçamento (ponteiro para mm é NULL).

São preemptivas e escalonáveis como qualquer outro processo.

São criadas por apenas outras kernel threads. Assim como os processos normais, são criados através

da syscall clone() com o uso de flags especiais. Exemplos: pdflush, ksoftirqd, nfsd (equivalente).

Page 19: Process management - Jorge Peixoto

Process Management19

Finalização de ProcessosFinalização de Processos

O kernel libera os recursos e notifica o processo pai.

A finalização do processo pode ocorrer:– Voluntariamente e explicitamente, através da

chamada a syscall exit();– Voluntariamente e implicitamente, com o retorno da

função main() de qualquer programa;– Involuntariamente, quando o processo recebe um

sinal ou quando ocorre um exceção que não pode tratar ou ignorar.

Page 20: Process management - Jorge Peixoto

Process Management20

do_exit()do_exit() Ativa o flag PF_EXITING em task_struct. Invoca del_timer_sync() para remover qualquer timer de

kernel. Após o retorno, é garantido que nenhum timer estará enfileirado e nenhum timer handler estará rodando.

Se BSD process accounting estiver ativo, chama acct_process().

Chama __exit_mm() para liberar mm_struct, se não estiver compartilhado, desaloca.

Chama exit_sem() para liberar semáforos. Chama __exit_files(), __exit_fs(), exit_namespace(),

and exit_sighand(). Atribuí o código de saída do processo (variável exit_code de

task_struct) para posterior análise pelo processo pai. Chama exit_notify() e atribui o estado TASK_ZOMBIE. Chama schedule().

Page 21: Process management - Jorge Peixoto

Process Management21

Remoção do Descritor de ProcesosRemoção do Descritor de Procesos

Finalizada a syscall exit(), o processo ainda existe!

Somente após chamar a syscall wait4(), o processo é liberado (descritor de processos é desalocado).

Os únicos objetos associados ao processo são a sua pilha de kernel, thread_info e task_struct.

O funcionamento padrão do wait() é suspender o processor chamador até que um filho finalize. Retorna o PID do filho.

Page 22: Process management - Jorge Peixoto

Process Management22

release_task()release_task() Sua função é liberar o descritor de processos. Chama free_uid() para decrementar o contador de

uso de processos do usuário. Unhash_process(), remove o processo da tabela hash

de PID e remove o processo da task list. Se ptrace foi usado, repatriar o processo para o pai

original e remove da ptrace list. Chama put_task_struct() para liberar as páginas

contendo a pilha de kernel do processo e a estrutura thread_info e desalocar o slab cache contendo task_struct.

Page 23: Process management - Jorge Peixoto

Process Management23

Processos ÓrfãosProcessos ÓrfãosReparent o processo órfão a um processo do

grupo que pertence, se falha, ao processo init.Evitar o acumulo de processo zumbis,

desperdiçando memória.

Page 24: Process management - Jorge Peixoto

Process Management24

RevisãoRevisão Processo é uma das abstrações fundamentais do Linux Relação entre processos e threads Como o processo é representado no Linux kernel: task_struct e thread_info

Como é criado: fork() e clone() Como novos imagens de executáveis são carregados: exec()

Como o pai coleta informações dos seus “falecidos” processos filhos: wait()

Como um processo morre: exit()