SinaisTopO KernelProcessos e Threads

Processos e Threads

Alocação de Memória

Modos de Execução e Contextos

Estados de um Processo

Contexto de um Processo

Credenciais de um Processo

A Área-U

A Estrutura proc

Linux: task_struct

Em /usr/src/linux/include/kernel/sched.h

struct task_struct {
        /*
         * offsets of these are hardcoded
         * elsewhere - touch with care
         */
    /* -1 unrunnable, 0 runnable, >0 stopped*/
        volatile long state;
    /* per process flags, defined below */
        unsigned long flags;
        int sigpending;
    /* thread address space:
           0-0xBFFFFFFF for user-thead
           0-0xFFFFFFFF for kernel-thread
    */
        mm_segment_t addr_limit;
        struct exec_domain *exec_domain;
        volatile long need_resched;
        unsigned long ptrace;
    /* Lock depth */
        int lock_depth;



/*
 * offset 32 begins here on 32-bit platforms. 
 * We keep all fields in a single cacheline
 * that are needed for
 * the goodness() loop in schedule().
 */
        long counter;
        long nice;
        unsigned long policy;
        struct mm_struct *mm;
        int has_cpu, processor;
        unsigned long cpus_allowed;
        /*
         * (only the 'next' pointer fits
         *  into the cacheline, but
         * that's just fine.)
         */
        struct list_head run_list;
        unsigned long sleep_time;

        struct task_struct *next_task,
                           *prev_task;
        struct mm_struct *active_mm;





/* task state */
        struct linux_binfmt *binfmt;
        int exit_code, exit_signal;
  /*  The signal sent when the parent dies  */
        int pdeath_signal;
        /* ??? */
        unsigned long personality;
        int dumpable:1;
        int did_exec:1;
        pid_t pid;
        pid_t pgrp;
        pid_t tty_old_pgrp;
        pid_t session;
        pid_t tgid;
  /* boolean value for session group leader */
        int leader;
  /* 
   * pointers to (original) parent process,
   * youngest child, younger sibling,
   * older sibling, respectively. 
   * (p->father can be replaced with 
   * p->p_pptr->pid)
   */
        struct task_struct *p_opptr, *p_pptr,
                           *p_cptr, *p_ysptr,
                           *p_osptr;
        struct list_head thread_group;

        /* PID hash table linkage. */
        struct task_struct *pidhash_next;
        struct task_struct **pidhash_pprev;

        /* for wait4() */
        wait_queue_head_t wait_chldexit;
            /* for vfork() */
        struct semaphore *vfork_sem;
        unsigned long rt_priority;
        unsigned long it_real_value,
               it_prof_value, it_virt_value;
        unsigned long it_real_incr,
               it_prof_incr, it_virt_incr;
        struct timer_list real_timer;
        struct tms times;
        unsigned long start_time;
        long per_cpu_utime[NR_CPUS],
             per_cpu_stime[NR_CPUS];
/* mm fault and swap info: this can arguably
    be seen as either mm-specific or
    thread-specific */
        unsigned long min_flt, maj_flt, nswap,
                 cmin_flt, cmaj_flt, cnswap;
        int swappable:1;
/* process credentials */
        uid_t uid,euid,suid,fsuid;
        gid_t gid,egid,sgid,fsgid;
        int ngroups;
        gid_t   groups[NGROUPS];
        kernel_cap_t   cap_effective, 
               cap_inheritable, cap_permitted;
        int keep_capabilities:1;
        struct user_struct *user;
/* limits */
        struct rlimit rlim[RLIM_NLIMITS];
        unsigned short used_math;
        char comm[16];
/* file system info */
        int link_count;
        /* NULL if no tty */
        struct tty_struct *tty; 
     /* How many file locks are being held */
        unsigned int locks;
/* ipc stuff */
        struct sem_undo *semundo;
        struct sem_queue *semsleeping;
/* CPU-specific state of this task */
        struct thread_struct thread;
/* filesystem information */
        struct fs_struct *fs;
/* open file information */
        struct files_struct *files;
/* signal handlers */
        /* Protects signal and blocked */
        spinlock_t sigmask_lock;     
        struct signal_struct *sig;

        sigset_t blocked;
        struct sigpending pending;

        unsigned long sas_ss_sp;
        size_t sas_ss_size;
        int (*notifier)(void *priv);
        void *notifier_data;
        sigset_t *notifier_mask;
        
/* Thread group tracking */
        u32 parent_exec_id;
        u32 self_exec_id;
/* Protection of (de-)allocation:
     mm, files, fs, tty */
        spinlock_t alloc_lock;
};

Linux: task_struct

FreeBSD: proc e user

Execução em Modo Kernel

Sincronização em Unix

Sincronização: Implementação

Escalonamento em Unix

Partilha do CPU:

Sinais em Unix

Novos Processos

fork()

exec()

init

Único processo que não resulta de fork(). Ver init/main.c:

init() {
 lock_kernel();
 do_basic_setup();
 /*
  * Ok, we have completed the initial
  * bootup, and we're essentially up
  * and running. Get rid of the initmem
  * segments and start the user-mode stuff..
  */
 free_initmem();
 unlock_kernel();

 if (open("/dev/console", O_RDWR, 0) < 0)
   printk("Warning: unable to open
            an initial console.\n");

 (void) dup(0);
 (void) dup(0);
      
\T\pagebreak
 /*
  * We try each of these until one succeeds.
  *
  * The Bourne shell can be used instead
  * of init if we are 
  * trying to recover a really broken machine.
  */
 if (execute_command)
  execve(execute_command,argv_init,envp_init);
 execve("/sbin/init",argv_init,envp_init);
 execve("/etc/init",argv_init,envp_init);
 execve("/bin/init",argv_init,envp_init);
 execve("/bin/sh",argv_init,envp_init);
 panic("No init found. 
        Try passing init= option to kernel.");
}

Terminação do Processo: exit()

Terminação do Processo: wait()

Porquê Threads

Concorrência em Processos

Tipos de Threads

Problema, separação entre UT e LWP:

UTs e LWPs

Suporte a LWPs no Kernel

Bibliotecas de Threads

P-threads:

Implementação de Bibliotecas

Solaris: Kernel Level Threads

Kernel Threads são usados para actividade assíncrona (callouts, STREAMs, escrita no disco) e para suportar LWPs:

Kernel organizado como conj. de KTs: alguns LWPs, outros no kernel.

KTs são preemptible.

Primitivas de sincronização: semáforos, condições, etc, tentam impedir inversão de prioridades.

Solaris: LWPs

Cada LWP é associado a um KT durante a sua vida.

Em lwp:

LWP é swappable, logo máscaras têm que estar em KT. No SPARC g7 refere lwp.

Sincronização como para KT: bloqueantes ou não.

Signal handlers são comuns ao processo mas máscaras pertencem ao LWP (e possivelmente stack).

Solaris: UTs

UT são implementados por bibliotecas. Podem ser associados a LWPs ou não

Solaris: Interrupts

Solaris usa mutex e semáforos para interrupts, e usa interrupt threads para atender a interrupts:

Solaris: Interrupts

Solaris: Chamadas de Sistema

Chamadas de sistema:

Mach: Threads

Mach suporta:

Mach: Tasks

Task contém:

Mach: Threads

Thread contém:

Digital Unix

Baseado em Mach 2.5:

Mach: Continuações

Problema:

Mach 3.0 usa continuações, uma função a executar quando o thread bloqueia:

Windows NT: Processos

Windows NT: Executive Process Block

Windows NT: CreateProcess

Windows NT: o PEB

Linux: clone

Scheduler Activations

Integrar UTs e Kernel:

Ideia veio de Anderson

Scheduler Activations: Abstrações

Upcall:
Kernel chama biblioteca;
Scheduler Activation:
contexto que pode ser usado para correr um UT (semelhante a LWP).

Esquema extremamente rápido.


vitor@cos.ufrj.br

SinaisTopO KernelProcessos e Threads