A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

SVCs para Controle de Processos no Unix

Apresentações semelhantes


Apresentação em tema: "SVCs para Controle de Processos no Unix"— Transcrição da apresentação:

1 SVCs para Controle de Processos no Unix
id, no retorno da chamada, contém, no processo pai, o identificador do processo filho criado; Para o processo filho o valor da variável id será zero; Pode-se selecionar o trecho de código que será executado pelos processos com o comando if; Sistemas Operacionais

2 Criação de Processos (1)
A maioria dos sistemas operacionais usa um mecanismo de spawn para criar um novo processo a partir de um outro executável. LPRM/DI/UFES Sistemas Operacionais

3 Criação de Processos (2)
Exemplo Não é exatamente assim no Unix! LPRM/DI/UFES Sistemas Operacionais

4 Criação de Processos (3)
Exemplo Grafo de Precedência LPRM/DI/UFES Sistemas Operacionais

5 Criação de Processos (4)
Exercício: Desenhar o grafo de precedência LPRM/DI/UFES Sistemas Operacionais

6 Criação de Processos no UNIX
No Unix, são usadas duas funções distintas relacionadas à criação e execução de programas. São elas: fork(): cria processo filho idêntico ao pai, exceto por alguns atributos e recursos. exec(): carrega e executa um novo programa A sincronização entre processo pai e filho(s) é feita através da SVC wait(), que bloqueia o processo pai até que um processo filho termine. LPRM/DI/UFES Sistemas Operacionais

7 A SVC fork() (1) No Unix, a única forma de se criar um novo processo (dito processo filho) é através da invocação da chamada ao sistema fork(). Fork() duplica/clona o processo que executa a chamada. O processo filho é uma cópia fiel do pai, ficando com uma cópia do segmento de dados, heap e stack; no entanto, o segmento de texto (código) é muitas vezes partilhado por ambos. Processos pai e filho continuam a sua execução na instrução seguinte à chamada fork(). Em geral, não se sabe quem continua a executar imediatamente após uma chamada a fork() (se é o pai ou o filho). Depende do algoritmo de escalonamento. LPRM/DI/UFES Sistemas Operacionais

8 A SVC fork() (2) O processo filho herda do pai alguns atributos, tais como: variáveis de ambiente, variáveis locais e globais, privilégios e prioridade de escalonamento. O processo filho tem seu próprio espaço de endereçamento, com cópia de todas as variáveis do processo pai. Essas são independentes em relação às variáveis do processo pai. O processo filho também herda alguns recursos, tais como arquivos abertos e devices. Alguns atributos e recursos, tais como PID, PPDI, sinais pendentes e estatísticas do processo, não são herdados pelo processo filho. A função fork() é invocada uma vez (no processo-pai) mas retorna duas vezes, uma no processo que a invocou e outra num novo processo agora criado, o processo-filho. O retorno da função fork(), no processo pai, é igual ao número do pid do processo filho recém criado (todos os processos em Unix têm um identificador, geralmente designado por pid – process identifier). O retorno da função fork()é igual a 0 (zero) no processo filho. LPRM/DI/UFES Sistemas Operacionais

9 A SVC fork() (3) LPRM/DI/UFES Sistemas Operacionais

10 A SVC fork() (4) LPRM/DI/UFES Sistemas Operacionais

11 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 compartilhar uma única cópia somente de leitura. Se uma escrita é feita, uma duplicação é realizada 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 inicial do fork() é a duplicação da tabela de páginas do processo pai e a criação de um novo proc Struct (c/ PID para o filho). LPRM/DI/UFES Sistemas Operacionais

12 SVCs para Identificação do Processo no UNIX
Como visto, todos os processos em Unix têm um identificador, geralmente designados por pid (process identifier). Os identificadores são números inteiros diferentes para cada processo (ou melhor, do tipo pid_t definido em sys/types.h). É sempre possível a um processo conhecer o seu próprio identificador e o do seu pai. Os serviços a utilizar para conhecer pid’s (além do serviço fork()) são: LPRM/DI/UFES Sistemas Operacionais

13 User ID e Group ID No Unix, cada processo tem de um proprietário, um usuário que seja considerado seu dono. Através das permissões fornecidas pelo dono, o sistema sabe quem pode e não pode executar o processo em questão. Para lidar com os donos, o Unix usa os números UID (User Identifier) e GID (Group Identifier). Os nomes dos usuários e dos grupos servem apenas para facilitar o uso humano do computador. Cada usuário precisa pertencer a um ou mais grupos. Como cada processo (e cada arquivo) pertence a um usuário, logo esse processo pertence ao grupo de seu proprietário. Assim sendo, cada processo está associado a um UID e a um GID. Os números UID e GID variam de 0 a Dependendo do sistema, o valor limite pode ser maior. No caso do usuário root, esses valores são sempre 0 (zero). Assim, para fazer com que um usuário tenha os mesmos privilégios que o root, é necessário que seu GID seja 0. Primitivas: uid_t getuid(void) / uid_t geteuid(void) gid_t getgid(void) / gid_t getegid(void) LPRM/DI/UFES Sistemas Operacionais

14 Exemplo 1: #include <stdio.h> #include <unistd.h>
int main (void) { printf("I am process %ld\n", (long)getpid()); printf("My parent is %ld\n", (long)getppid()); printf("My real user ID is %5ld\n", (long)getuid()); printf("My effective user ID is %5ld\n", (long)geteuid()); printf("My real group ID is %5ld\n", (long)getgid()); printf("My effective group ID is %5ld\n", (long)getegid()); return 0; } LPRM/DI/UFES Sistemas Operacionais

15 Exemplo 2: simplefork.c #include <stdio.h>
#include <unistd.h> int main(void) { int x; x = 0; fork(); x = 1; printf("I am process %ld and my x is %d\n", (long)getpid(), x); return 0; } LPRM/DI/UFES Sistemas Operacionais

16 Comando ps COLUNAS (maiores informações: % man ps)
WCHAN    address of the kernel function where the process is sleeping (use wchan if   you want the kernel function name). Running tasks will display a dash (’-’) in this column. he S column tells us what state the process is in. The C column is the processor utilization. With the exception of the ps command, all of the other processes listed are waiting for some event, such as another process to exit or (as in the case of shell processes) are waiting for user input. Note that in this example all of the entries have a 0 (zero) in the C column. This does not mean they have used no CPU time, but rather it is so low that it is reported as zero. The PRI column shows us the priority of the process followed by the nice value (NI). COLUNAS (maiores informações: % man ps) S : estado do processo. C: utilização da CPU. Uso muito baixo é reportado como zero. PRI: prioridade do processo. NI: valor do “nice”. WCHAN: endereço da rotina de kernel onde o processo dorme. Processos em execução são marcados com hífen (’-’). LPRM/DI/UFES Sistemas Operacionais

17 Estrutura Geral do fork()
pid=fork(); if(pid < 0) { /* falha do fork */ } else if (pid > 0) { /* código do pai */ else { //pid == 0 /* código do filho */ LPRM/DI/UFES Sistemas Operacionais

18 Exemplo 3: twoprocs.c #include <stdio.h>
#include <unistd.h> #include <sys/types.h> int main(void) { pid_t childpid; childpid = fork(); if (childpid == -1) { //error perror("Failed to fork"); return 1; } if (childpid == 0) /* child code */ printf("I am child %ld\n", (long)getpid()); else /* parent code */ printf("I am parent %ld\n", (long)getpid()); return 0; LPRM/DI/UFES Sistemas Operacionais

19 Exercício 1: Montar o Grafo de Precedência
c1 = fork(); /* fork number 1 */ if (c1 == 0) c2 = fork(); /* fork number 2 */ fork(); /* fork number 3 */ if (c2 > 0) fork(); /* fork number 4 */ exit(); LPRM/DI/UFES Sistemas Operacionais

20 Exemplo 5: simplechain.c
1 2 3 4 Exemplo 5: simplechain.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main (int argc, char *argv[]) { pid_t childpid = 0; int i, n; if (argc != 2){ /* check for valid number of command-line arguments */ fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } n = atoi(argv[1]); for (i = 1; i < n; i++) if (childpid = fork()) //only the parent enters break; fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid); return 0; Atoi: Parses the C string str interpreting its content as an integral number, LPRM/DI/UFES Sistemas Operacionais

21 Exemplo 6: simplefan.c 4 1 2 3 #include <stdio.h>
#include <stdlib.h> #include <unistd.h> int main (int argc, char *argv[]) { pid_t childpid = 0; int i, n; /* check for valid number of command-line arguments */ ... n = atoi(argv[1]); for (i = 1; i < n; i++) if ((childpid = fork()) <= 0) //only the child (or error) enters break; fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid); return 0; } LPRM/DI/UFES Sistemas Operacionais

22 Exercício 2 Explique o que acontece quando se altera a linha abaixo no programa simplefan.c (childpid = fork()) <= 0 para (childpid = fork()) == -1 LPRM/DI/UFES Sistemas Operacionais

23 Término de Processos no Unix
Um processo pode terminar normalmente ou anormalmente nas seguintes condições: Normal: Executa return na função main(), o que é equivalente à chamar exit(); Invoca diretamente a função exit()da biblioteca C; Invoca diretamente o serviço do sistema _exit(). Anormal: Invoca o função abort(); Recebe sinais de terminação gerados pelo próprio processo, ou por outro processo, ou ainda pelo Sistema Operacional. A função abort() Destina-se a terminar o processo em condições de erro e pertence à biblioteca padrão do C. Em Unix, a função abort() envia ao próprio processo o sinal SIGABRT, que tem como conseqüência terminar o processo. Esta terminação deve tentar fechar todos os arquivos abertos. LPRM/DI/UFES Sistemas Operacionais

24 A Chamada exit() void exit(code)
O argumento code é um número de 0 a 255, escolhido pela aplicação e que será passado para o processo pai na variável status. A chamada exit() termina o processo; portanto, exit() nunca retorna Chama todos os exit handlers que foram registrados na função atexit(). A memória alocada ao segmento físico de dados é liberada. Todos os arquivos abertos são fechados. É enviado um sinal para o pai do processo. Se este estiver bloqueado esperando o filho, ele é acordado. Se o processo que invocou o exit() tiver filhos, esses serão “adotados” pelo processo init. Faz o escalonador ser invocado. LPRM/DI/UFES Sistemas Operacionais

25 Processo “Zombie” O que acontece se o processo filho termina antes do pai? No Unix, o processo pai sempre tem que saber o status do término do processo filho. Por isso, sempre que um processo termina, o kernel guarda algumas informações sobre ele, de modo que essas informações estejam disponíveis para o processo pai quando ele executar wait ou waitpid. Na terminologia do Unix, um processo que já terminou (já está morto) mas cujo pai ainda não executou o comando wait ou waitpid é dito um processo “zombie”. O que acontece se o processo pai termina antes do filho? O processo init (PID 1) torna-se pai de todo e qualquer processo cujo pai termina antes do filho (isto é, processos órfão é adotado pelo processo init). Sempre que um filho do init termina, ele chama wait/waitpid. LPRM/DI/UFES Sistemas Operacionais

26 A SVC wait() do Unix (1) Como processos descobrem se seu filho terminou? Chamada wait() feita pelo pai – retorna o PID do processo filho que terminou execução Normalmente, pai executando wait() é bloqueado até filho terminar Se não existir filhos no estado zombie, esperar que um filho termine waitpid() Para esperar um filho específico Também pode esperar por qualquer filho waitpid(-1,...,...) ~ wait(...) #include <sys/wait.h> pid_t wait(int *stat_loc); pid_t waitpid(pid_t pid, int *stat_loc, int options); LPRM/DI/UFES Sistemas Operacionais

27 A SVC wait() do Unix (2) Em caso de erro
retorna -1 Seta a variável global errno ECHILD: não existem filhos para termitar (wait), ou pid não existe (waitpid) EINTR: função foi interrompida por um sinal EINVAL: o parâmetro options do waitpid estava inválido Solução para que um processo pai continue esperando pelo término de um processo filho, mesmo que o pai seja interrompido por um sinal: LPRM/DI/UFES Sistemas Operacionais

28 A SVC wait() do Unix (3) A opção WNOHANG na chamada waitpid permite que um processo pai verifique se um filho terminou, sem que este primeiro bloqueie caso filho ñ tenha terminado Neste caso waitpid retorna 0 pid_t child pid; while (childpid = waitpid(-1, NULL, WNOHANG)) if ((childpid == -1) && (errno != EINTR)) break; Funçao que pode ser usada no INIT p/ liberar os zumbies Entra no if se ñ tiver mais filhos ou se erros nos parametros LPRM/DI/UFES Sistemas Operacionais

29 Exemplo 7: fanwait.c #include <stdio.h>
#include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include "restart.h" int main(int argc, char *argv[]) { pid_t childpid; int i, n; ... for (i = 1; i < n; i++) if ((childpid = fork()) <= 0) break; while(r_wait(NULL) > 0) ; /* wait for all of your children */ fprintf(stderr, "i:%d proc.ID:%ld parentID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid); return 0; } LPRM/DI/UFES Sistemas Operacionais

30 Exercício 3 Referente ao programa fanwait.c
Explique o que acontece quando coloca o printf antes do while ? Explique o que acontece se substituirmos a chamada r_wait por wait(NULL) simplesmente ? LPRM/DI/UFES Sistemas Operacionais

31 Valores de stat_loc (1) O argumento stat_loc: ponteiro p/a uma variável inteira Um filho sempre retorna seu status ao chamar exit ou ao retornar do main 0: indica EXIT_SUCCESS outro valor: indica EXIT_FAILURE MACROS WIFEXITED(status) – permite determinar se o processo filho terminou normalmente WEXITSTATUS(status) – retorna o código de saída do processo filho WIFSIGNALED(status)– permite determinar se o processo filho terminou devido a um sinal WTERMSIG(status) – permite obter o número do sinal que provocou a finalização do processo filho WIFSTOPPED(status) – permite determinar se o processo filho que provocou o retorno se encontra congelado (stopped) WSTOPSIG(status) – permite obter o número do sinal que provocou o congelamento do processo filho LPRM/DI/UFES Sistemas Operacionais

32 Valores de stat_loc (2) Exemplo LPRM/DI/UFES Sistemas Operacionais

33 A SVC exec() do Unix (1) Quando um processo invoca uma das funções exec, ele é completamente substituído por um novo programa Substitui o processo corrente (os seus segmentos text, data, heap e stack) por um novo programa carregado do disco O novo programa começa a sua execução a partir da função main() O identificador do processo não é alterado De fato, nenhum novo processo é criado Valor de retorno Sucesso - não retorna Erro - retorna o valor -1 e seta a variável errno com o código específico do erro Quando um processo executando um programa A quer executar outro programa B: Primeiramente ele deve criar um novo processo usando fork() Em seguida, o processo recém criado deve substituir todo o seu programa pelo programa B, chamando uma das primitivas da família exec LPRM/DI/UFES Sistemas Operacionais

34 A SVC exec() do Unix (1) LPRM/DI/UFES Sistemas Operacionais

35 Exemplo de Uso: fork() – exec()
#incude <stdio.h> main( int argc, char *argv[] ) { int pid; /* fork a child process */ pid = fork(); /* check fork() return code */ if ( pid < 0 ) { /* some error occurred */ fprintf( stderr, “Fork failed!\n” ); exit( -1 ); } else if ( pid == 0 ) { /* this is the child process */ execl( “/bin/ls”, “ls”, NULL ); /* morph into “ls” */ } else { /* this is the parent process. Wait for child to complete */ wait( NULL ); printf( “Child completed -- parent now exiting.\n” ); exit( 0 ); } LPRM/DI/UFES Sistemas Operacionais

36 A SVC exec() do Unix (2) O processo que executou a função exec mantém as seguintes informações pid e o ppid user, group, session id Mascara de sinais Alarmes Terminal de controle Diretórios raiz e corrente Informações sobre arquivos abertos Limites de uso de recursos Estatísticas e informações de accounting LPRM/DI/UFES Sistemas Operacionais

37 Funções exec (1) int execl(const char *pathname, const char *arg0, ...) int execv(const char *pathname, char *const argv[]) int execlp(const char *filename, const char *arg0, ...) int execvp(const char *filename, char *const argv[]) int execle(const char *pathname, const char *arg0, ..., char *const envp[]) int execve(const char *pathname, char *const argv[], char *const envp[]) LPRM/DI/UFES Sistemas Operacionais

38 Funções exec (2) Sufixos l v e p
lista de argumentos (terminada com NULL) v argumentos num array de strings (terminado com NULL) e variáveis de ambiente num array de strings (terminado com NULL) p procura executável nos diretórios definidos na variável de ambiente PATH (echo $PATH) LPRM/DI/UFES Sistemas Operacionais

39 Funções exec (3) Relações entre as funções exec LPRM/DI/UFES
Sistemas Operacionais

40 Funções exec (4) Se alguma das funções retorna, um erro terá ocorrido
Valores possíveis na variável global errno E2BIG Lista de argumentos muito longa EACCES Acesso negado EINVAL Sistema não pode executar o arquivo ENAMETOOLONG Nome de arquivo muito longo ENOENT Arquivo ou diretório não encontrado ENOEXEC Erro no formato de exec ENOTDIR Não é um diretório LPRM/DI/UFES Sistemas Operacionais

41 Funções exec (4) Executar os seguintes comandos ls -l /etc
ls -l /etc/s*.conf LPRM/DI/UFES Sistemas Operacionais

42 Funções exec (5) Um programa que cria um processo filho para executar “ls -l” LPRM/DI/UFES Sistemas Operacionais

43 Funções exec (5) Um programa que cria um processo filho para executar um comando (com ou sem parâmetros) passado como parâmetro execcmd.c ... LPRM/DI/UFES Sistemas Operacionais

44 O shell do UNIX (1) Quando o interpretador de comandos UNIX interpreta comandos, ele chama fork e execl ... Lê comando para o interpretador de comandos If (fork()==0) exec...(command, lista_arg ...) LPRM/DI/UFES Sistemas Operacionais

45 O shell do UNIX (2) exec LPRM/DI/UFES Sistemas Operacionais

46 O shell do UNIX (3) LPRM/DI/UFES Sistemas Operacionais

47 Processos background e foreground (1)
Existem vários tipos de processos no Linux: processos interativos, processos em lote (batch) e Daemons. Processos interativos são iniciados a partir de uma sessão de terminal e por ele controlados. Quando executamos um comando do shell, entrando simplesmente o nome do programa seguido de <enter>, estamos rodando um processo em foreground. Um programa em foreground recebe diretamente sua entrada (stdin) do terminal que o controla e, por outro lado, toda a sua saida (stdout e stderr) vai para esse mesmo terminal. Digitando Ctrl-Z, suspendemos esse processo, e recebemos do shell a mensagem Stopped (talvez com mais alguns caracteres dizendo o número do job e a linha de comando). A maioria dos shells tem comandos para controle de jobs, para mudar o estado de um processo parado para background, listar os processos em background, retornar um processo de back para foreground, de modo que o possamos controlar novamente com o terminal. No bash o comando jobs mostra os jobs correntes, o bg restarta um processo suspenso em background e o comando fg o restarta em foreground. Daemons ou processos servidores, mais freqüentemente são iniciados na partida do sistema, rodando continuamente em background enquanto o sistema está no ar, e esperando até que algum outro processo solicite o seu serviço (ex: sendmail). LPRM/DI/UFES Sistemas Operacionais

48 Processos de background e foreground (2)
O Comando Jobs Serve para visualizar os processos que estão parados ou executando em segundo plano (background). Quando um processo está nessa condição, significa que a sua execução é feita pelo kernel sem que esteja vinculada a um terminal. Em outras palavras, um processo em segundo plano é aquele que é executado enquanto o usuário faz outra coisa no sistema. Para executar um processo em background usa-se o “&” (ex: ls –l &). Assim, uma dica para saber se o processo está em background é verificar a existência do caractere & no final da linha. Se o processo estiver parado, geralmente a palavra "stopped" aparece na linha, do contrário, a palavra "running" é exibida. Os comandos fg e bg O fg é um comando que permite a um processo em segundo plano (ou parado) passar para o primeiro plano (foreground), enquanto que o bg passa um processo do primeiro para o segundo plano. Para usar o bg, deve-se paralisar o processo. Isso pode ser feito pressionando-se as teclas Ctrl + Z. Em seguida, digita-se o comando da seguinte forma: bg +número O número mencionado corresponde ao valor de ordem informado no início da linha quando o comando jobs é usado. Quanto ao comando fg, a sintaxe é a mesma: fg +número LPRM/DI/UFES Sistemas Operacionais

49 Sessões e grupos de processos (1)
No Unix, além de ter um PID, todo processo também pertence a um grupo. Um process group é é uma coleção de um ou mais processos. Todos os processos dentro de um grupo são tratados como uma única entidade. A função getpgrp() retorna o número do grupo do processo chamador. Cada grupo pode ter um processo líder, que é identificado por ter o seu PID igual ao seu GoupID. É possível ao líder criar novos grupos, criar processos nos grupos e então terminar (o grupo ainda existirá mesmo se o líder terminar; para isso tem que existir pelo menos um processo no grupo - process group lifetime). Uma sessão é um conjunto de grupos de processos. Grupos ou sessões são também herdadas pelos filhos de um processo. Um servidor, por outro lado, deve operar independentemente de outros processos. Como fazer então que um processo servidor atenda a todos os grupos e sessões? A primitiva setsid()obtém um novo grupo para o processo . Ela coloca o processo em um novo grupo e sessão, tornando-o independente do seu terminal de controle (setpgrp ié uma alternativa para isso). É usada para passar um processo de foreground em background. LPRM/DI/UFES Sistemas Operacionais

50 Sessões e grupos de processos (1)
Uma sessão é um conjunto de grupos de processos Cada sessão pode ter um único terminal controlador no máximo 1 grupo de processos de foregroud n grupos de processos de background LPRM/DI/UFES Sistemas Operacionais

51 Colocando um processo em background
Uso de setsid para que o processo pertença a uma outra sessão , e a um outro grupo, se tornando de background LPRM/DI/UFES Sistemas Operacionais

52 Resumo SVCs: Processos
fork: cria um novo processo que é uma cópia do processo pai. O processo criador e o processo filho continuam em paralelo, e executam a instrução seguinte à chamada de sistema. wait: suspende a execução do processo corrente até que um filho termine. Se um filho terminou antes desta chamada de sistema(estado zombie), os recursos do filho são liberados e o processo não fica bloqueado, retornando imediatamente. exit: termina o processo corrente. Os filhos, se existirem, são herdados pelo processo init e o processo pai é sinalizado. exec: executa um programa, substituindo a imagem do processo corrente pela imagem de um novo processo, identificado pelo nome de um arquivo executável, passado como argumento. kill: usada para enviar um sinal para um processo ou grupo de processos. O sinal pode indicar a morte do processo. sleep: suspende o processo pelo tempo especificado como argumento. LPRM/DI/UFES Sistemas Operacionais

53 Referências Kay A. Robbins, Steven Robbins, UNIX Systems Programming: Communication, Concurrency and Threads, 2nd Edition Capítulo 3 LPRM/DI/UFES Sistemas Operacionais


Carregar ppt "SVCs para Controle de Processos no Unix"

Apresentações semelhantes


Anúncios Google