baseado na vers - PowerPoint PPT Presentation

About This Presentation
Title:

baseado na vers

Description:

Process Management baseado na vers o 2.6 do kernel do Linux PESC / COPPE / UFRJ Sistemas Operacionais Prof. Vitor Santos Costa, Ph.D. Jorge Luiz Silva Peixoto – PowerPoint PPT presentation

Number of Views:62
Avg rating:3.0/5.0
Slides: 25
Provided by: cosUfrjB6
Category:
Tags: baseado | clone | vers

less

Transcript and Presenter's Notes

Title: baseado na vers


1
Process Management
  • baseado na versão 2.6 do kernel do Linux

PESC / COPPE / UFRJ Sistemas Operacionais Prof.
Vitor Santos Costa, Ph.D.
Jorge Luiz Silva Peixoto jorge_at_ravel.ufrj.br jorge
peixoto_at_cos.ufrj.br, gmail.com
2
Introdução e Motivação
  • O que é um processo?
  • Um programa em execução. É composto de

Estado
Espaço de endereçamento
Sinais pendentes
Arquivos abertos
Kernel data
Threads
Pilha
PC
Registradores
3
Introdução e Motivação
  • Ciclo de vida do processo

4
Programaçã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

5
Descritor 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

6
Descritor 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.

7
Descritor 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.

8
Estados 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.

9
Contexto de Processo vs de SistemaEspaço de
Usuário vs 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.

10
Hierarquia 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.

11
Criaçã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", ...) lt 0)
  • perror "execve failed")
  • exit (1)
  • else if(result lt 0)
  • perror("fork") / fork failed /
  • )
  • / parent continues here /

12
Copy-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.

13
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.

14
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.

15
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.

16
Threads
  • 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.

17
Threads 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)

18
Kernel 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).

19
Finalizaçã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.

20
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().

21
Remoçã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.

22
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.

23
Processos Órfãos
  • Reparent 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.

24
Revisã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()
Write a Comment
User Comments (0)
About PowerShow.com