Baixe o app para aproveitar ainda mais
Prévia do material em texto
Criação de processos em Unix A criação de processos em UNIX é feita através das chamadas de sistema fork e execve. Estes exercícios têm por objetivos mostrar exemplos do uso dessas chamadas e estimular o aluno a compreender sua dinâmica. Exercício 1 Dado o programa fork.c a seguir: fork.c /*Criação de processos em UNIX. Compilar com gcc -Wall fork.c -o fork Carlos Maziero, DINF/UFPR 2020*/ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main (){ int retval ; //cria variável ‘retval’ do tipo inteiro para receber o PID do filho printf ("Ola, sou o processo %5d\n", getpid()) ; //imprime número do processo atual (Pai) // Duplicando o processo retval = fork () ; ’fork’ clona o processo atual “pai” e retorna o PID processo filho para a variável ‘retval’ // Caso a função fork retorne 0 (zero), está se executando o processo filho. Caso a função retorne um valor diferente de 0 (zero), mas positivo, o processo pai está sendo executado. printf ("[retval: %5d] sou %5d, filho de %5d\n", retval, getpid(), getppid()) ; ; Ao executar esta linha no processo pai, ‘retval’ vai exibir o PID do filho, seguido do PID do processo atual/pai (getpid()) e o PID do pai do processo principal (getppid()) e, ao executar no processo filho, ‘retval’ vai exibir 0, seguido do PID do próprio processo atual/filho (getpid()) e, por fim, o PID do processo pai do processo atual/filho. if ( retval < 0 ) { //caso ‘retval’ seja ‘< 0’ significa que o filho não foi gerado pelo fork perror ("Erro") ; //formata o último erro encontrado durante uma chamada a um sistema ou função de biblioteca para a palavra entre aspas, neste caso “erro”. exit (1) ; }else if ( retval > 0 ) //caso ‘retval’ seja ‘<>0’ significa que o filho foi gerado pelo fork (Duplicando o processo pai) wait (0);//aguarda a processo filho terminar para retornar a execução do pai (0 - significando que o pai espera a morte de qualquer processo filho cujo ID do grupo é igual ao do processo chamado). else //significa que ‘retval’ é = 0, ou seja, o fork retornou 0, portanto estamos no processo filho. sleep (5) ; //aguarda 5 segundos printf ("Tchau de %5d!\n", getpid()) ; //exibe a mensagem “tchau de” e informa o PID do filho e depois o PID do pai. exit (0) ;// interrompe a execução do programa } 1. Analise seu código e o comente detalhadamente. 2. Desenhe o diagrama de tempo de sua execução. Exercício 2 Dado o programa fork-execve.c a seguir: fork-execve.c /* Criação de processos em UNIX, com execução de outro binário Compilar com gcc -Wall fork-execve.c -o fork-execve Carlos Maziero, DINF/UFPR 2020 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main (int argc, char *argv[], char *envp[]){//variáveis de ambiente int retval ;//cria variável ‘retval’ do tipo inteiro para receber o PID do filho printf ("Ola, sou o processo %5d\n", getpid());//imprime o PID do processo atual retval = fork ();//’fork’ clona o processo atual “pai” e retorna o PID processo filho para a variável ‘retval’ printf ("[retval: %5d] sou %5d, filho de %5d\n", retval, getpid(), getppid());//Ao executar esta linha no processo pai, ‘retval’ vai exibir o PID do filho, seguido do PID do processo atual/pai (getpid()) e o PID do pai do processo principal (getppid()) e, ao executar no processo filho, ‘retval’ vai exibir 0, seguido do PID do próprio processo atual/filho (getpid()) e, por fim, o PID do processo pai do processo atual/filho if ( retval < 0 )//a criação de um processo filho não foi bem-sucedida, não foi gerado pelo fork. { perror ("Erro: ");//formata o último erro encontrado durante uma chamada a um sistema ou função de biblioteca para a palavra entre aspas, neste caso “erro”. exit (1);//interrompe a execução do programa, 1 o sistema operacional é informado de que o programa terminou com um erro. } else if ( retval > 0 )// ‘retval’ contém o PID do filho recém-criado, o filho foi gerado pelo fork. wait (0);;//aguarda a processo filho terminar para retornar a execução do pai (0 - significando que o pai espera a morte de qualquer processo filho cujo ID do grupo é igual ao do processo chamado). else{ execve ("/bin/date", argv, envp); Um novo processo não é iniciado; a nova imagem do processo simplesmente se sobrepõe à imagem do processo original. A execvefunção é mais comumente usada para sobrepor uma imagem de processo que foi criada por uma chamada à fork função. Ou seja sobrescreve a imagem do processo pai. perror ("Erro");//formata o último erro encontrado durante uma chamada a um sistema ou função de biblioteca para a palavra entre aspas, neste caso “erro”. } printf ("Tchau de %5d!\n", getpid());//imprime o PID do processo atual/pai exit (0);//interrompe a execução do programa, 0 o sistema operacional é informado de que o programa terminou com sucesso. } 1. Analise seu código e o comente detalhadamente. 2. Desenhe o diagrama de tempo de sua execução. 3. O que ocorre se o programa a ser executado por execve não existir? Desenhe o diagrama de tempo que retrata essa situação. Se o programa não existir será exibido o erro correspondente a falha na execução "No such file or directory"; -1 será retornado se a chamada para execve não tiver êxito. Após isso será imprimido o próximo comando do processo pai, no caso "printf ("Tchau de %5d!\n", getpid())". Exercício 3 Dado o programa fork-print.c a seguir: fork-print.c /* Criação de processos em UNIX, com impressão de valores de variável. Compilar com gcc -Wall fork-print.c -o fork-print Carlos Maziero, DINF/UFPR 2020 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main () { int retval, x; ;//cria variável ‘retval’ do tipo inteiro para receber o PID do filho e, cria uma variável x do tipo inteiro. x = 0;//0 é atribuído a variável x. retval = fork();//’fork’ clona o processo atual “pai” e retorna o PID processo filho para a variável ‘retval’ printf ("No processo %5d x vale %d\n", getpid(), x);//imprime o PID do processo atual/pai e o valor da variável x que é zero if ( retval < 0 ){ )//a criação de um processo filho não foi bem-sucedida, não foi gerado pelo fork. perror ("Erro");//formata o último erro encontrado durante uma chamada a um sistema ou função de biblioteca para a palavra entre aspas, neste caso “erro”. exit (1);//interrompe a execução do programa, 1 o sistema operacional é informado de que o programa terminou com um erro. }else if ( retval > 0 ){ // ‘retval’ contém o PID do filho recém-criado, o filho foi gerado pelo fork. x = 0;//varivel x recebe 0 wait(0);//aguarda a processo filho terminar para retornar a execução do pai (0 - significando que o pai espera a morte de qualquer processo filho cujo ID do grupo é igual ao do processo chamado). } else{//’retval == 0’, Retornado ao processo filho recém-criado, está executando o processo filho. x++;//quando o processo filho estiver sendo executado (‘retval’== 0) a variável ‘x’ será incrementada de +1. sleep (5); //aguarda 5 segundos } printf("No processo %5d x vale %d\n", getpid(), x);//Quando estivermos no processo ‘filho’, o ‘x’ será 1, quando estivermos no processo ‘pai’ o ‘x’ será 0. exit (0); //interrompe a execução do programa, 0 o sistema operacional é informado de que o programa terminou com sucesso. } 1. Analise seu código e o comente detalhadamente. 2. Desenhe o diagrama de tempo de sua execução, indicando a evolução do valor da variável x.
Compartilhar