Linguagem de Programação IV

35
Linguagem de Programação IV Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação

description

Linguagem de Programação IV. Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação. Criação de processos paralelos. *baseado no material do Prof. Edison Ishikawa. Como iniciar um processo em C?. Similar a rodar um programa na linha de comando - PowerPoint PPT Presentation

Transcript of Linguagem de Programação IV

Page 1: Linguagem de Programação IV

Linguagem de Programação IV

Carlos Oberdan Rolim

Ciência da ComputaçãoSistemas de Informação

Page 2: Linguagem de Programação IV

Criação de processos paralelos

*baseado no material do Prof. Edison Ishikawa

Page 3: Linguagem de Programação IV

Como iniciar um processo em C?

Similar a rodar um programa na linha de comando

Usando a família de chamadas de sistemas exec…(…)

exec, execl, execv, execve, …

exec…() troca o processo corrente pelo novo que foi

especificado

Page 4: Linguagem de Programação IV

Exec....

O processo que chamou exec... É completamente substituído pelo novo programa, e o novo programa inicia sua execução como se fosse a função principal (main).

Não existe a criação de um novo processo mas sim a substituição do programa em execução

Com fork cria-se novos processos

Com exec inicia-se novos programas

Page 5: Linguagem de Programação IV

Exec – Diferentes funções

#include <unistd.h>

extern char **environ;

int execl( const char *path, const char *arg, ...);

int execle( const char *path, const char *arg , ..., char* const envp[]);

int execlp( const char *file, const char *arg, ...);

int execv( const char *path, char *const argv[]);

int execvp( const char *file, char *const argv[]);

Page 6: Linguagem de Programação IV

Exec

Diferenças

os execl(), para o qual o número de argumentos do programa

lançado é conhecido;

os execv(), para o qual esse número é desconhecido.

Em outras palavras, estes grupos de primitivas se

diferenciam pelo número de parâmetros passados.

Page 7: Linguagem de Programação IV

Exec

Diferenças

Modo de passar os argumentos

l = lista

execl, execlp, execle

Requer que cada um dos argumentos da linha de comando passada ao novo programa seja especificada por argumentos em separado. O último argumento é o null pointer - (char *) 0

Ex: char* arg0, char* arg1,....,char *argn, (char *) 0

v = vetor

execv, execvp, execve

Os argumentos são passados em um array de ponteiros, e o endereço deste array é passado como argumento

Page 8: Linguagem de Programação IV

Exec

PropriedadesO novo programa herda do processo que o invoca

Process ID e parent process IDReal user ID and real group IDSupplementary group IDsProcess group IDSession IDControlling terminalTime left until alarm clockCurrent working directoryRoot directoryFile mode creation maskFile locksProcess signal maskResource limitstms_utime, tms_stime, tms_cutime and tms ustime values

Page 9: Linguagem de Programação IV

execv() - exemplo

int execv(const char *path, char *const argv[])

path - command path

argv - argumentos (por um null no final)

Exemplo

char* prog[3]={“/usr/bin/ps”, “-a”, NULL};

execv(prog[0], prog);

Sugestão

consulte o man

Page 10: Linguagem de Programação IV

execv – exemplo

//gcc -o execv execv.c

//Existem diversas chamadas execXXX

#include <stdio.h>

#include <stdlib.h>

int main(){

char *my_program[3] = {"/bin/ls", "-l“,NULL};

execv(my_program[0],my_program);

printf("Cannot execute the command.\n");

return 0;

}

Page 11: Linguagem de Programação IV

Como executar vários processo em um único programa C?

System call fork()

quando um processo é “forkeado”, um novo processo

é criado

o segmento de dados e códigos do novo processo é o

mesmo do original

uma entrada na tabela de processos é criada para o

novo processo

Page 12: Linguagem de Programação IV

Fork

Processo 1

shell

fork

fork

Processo 1

Processo 2

PAI

FILHO

shell

shell exec

shell

ps

Page 13: Linguagem de Programação IV

System call fork

Copia o processo corrente e o executa

valor de retorno

ZERO no processo filho

O Id do processo filho (PID) no processo pai

use o valor de retorno para identificar aonde o

programa está

Page 14: Linguagem de Programação IV

Exemplo de fork

#include < stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main(){

if (fork()==0) {

printf(“Eu sou o filho\n”);

} else {

printf(“Eu sou o pai\n”);

}

}

Cria o processo filho

Código executado pelo filho

Código executado pelo pai

Page 15: Linguagem de Programação IV

Comportamento fork

Page 16: Linguagem de Programação IV

Comportamento do fork

Page 17: Linguagem de Programação IV

Sequencia fork() + execve()

Page 18: Linguagem de Programação IV

Fork vs Execve()

Page 19: Linguagem de Programação IV

O que acontece com o processo filho quando ele morre antes que o pai?

Page 20: Linguagem de Programação IV

Zombie

Quando o processo filho termina, ele tem que avisar o pai

antes de se matar

Se o pai não tomar conhecimento da morte do filho, o filho

se tornará um Zombie

O filho ficará no estado Zombie até que o pai tome

conhecimento

Page 21: Linguagem de Programação IV

Zombie

Os recursos usados pelo Zombie não são liberados!

Os processos zombie são rotulados como

<defunct> na listagem do comando

ps -u username

Se o seu programa(pai) rodar por muito tempo,

criando zombies, ele irá esgotar a memória

É obrigação do programador (sua) evitar isso

Page 22: Linguagem de Programação IV

Exemplo de zombie

#include <stdio.h>

#include <stdlib.h>

int main(){

int pid;

pid = fork();

if (pid==0){

printf(“I am child. I become a zombie now.\n”);

exit (0); child process terminate here

} else {

printf(“I am parent. I loop here. My child pid is [%d]\n”, pid);

while(1); parent process continue to run

}

return 0;

}

# ./zombie

I am parent. I loop here. My child pid is [2966]

I am child. I become a zombie now.

Saída do ps -ax

2965 pts/0 R+ 0:24 ./zombie

2966 pts/0 Z+ 0:00 [zombie] <defunct>

Page 23: Linguagem de Programação IV

Como evitar o Zombie

Usando a system call wait e waitpid no processo pai para tomar conhecimento da morte do filho

A função wait suspende a execução do processo até a morte de seu filho. Se o filho já estiver morto no instante da chamada da primitiva (caso de um processo zumbi), a função retorna imediatamente.

A função waitpid suspende a execução do processo até que o filho especificado pelo argumento pid tenha morrido. Se ele já estiver morto no momento da chamada, o comportamento é idêntico ao descrito anteriormente.

Page 24: Linguagem de Programação IV

Esperar pela terminação

Chamado também de join

Page 25: Linguagem de Programação IV

Wait: cenários possíveis

Page 26: Linguagem de Programação IV

Wait e Waitpid

#include <sys/types.h> #include <sys/wait.h>

pid_t wait(int *status) /* espera a morte de um filho */ pid_t waitpid(pid_t pid, int *status, int options)

int *status /* status descrevendo a morte do filho */

Valor de retorno: identificador do processo morto ou -1 em caso de erro. 

Page 27: Linguagem de Programação IV

Wait e Waitpid

O valor do argumento pid pode ser:

< -1 : significando que o pai espera a morte de qualquer filho cujo o ID do grupo é igual so valor de pid;

-1 : significando que o pai espera a morte de qualquer filho;

0 : significando que o pai espera a morte de qualquer processo filho cujo ID do grupo é igual ao do processo chamado;

> 0 : significando que o pai espera a morte de um processo filho com um valor de ID exatamente igual a pid.

Page 28: Linguagem de Programação IV

Wait e Waitpid

Se status é não nulo (NULL), wait e waitpid armazena a informação relativa a razão da morte do processo filho, sendo apontada pelo ponteiro status. Este valor pode ser avaliado com diversas macros que são listadas com o comando shell # man 2 wait.

O código de retorno via status indica a morte do processo que pode ser devido uma:

uma chamada exit(), e neste caso, o byte à direita de status vale 0, e o byte à esquerda é o parâmetro passado a exit pelo filho;

uma recepção de um sinal fatal, e neste caso, o byte à direita de status é não nulo. Os sete primeiros bits deste byte contém o número do sinal que matou o filho.

Page 29: Linguagem de Programação IV

Exemplo

St é um ponteiro global que recebe o retorno de

wait

Page 30: Linguagem de Programação IV

Exemplo

Page 31: Linguagem de Programação IV

Exemplo

#include <stdio.h>

#include <stdlib.h>

#include <sys/wait.h>

int main(){

int pid;

pid = fork();

if (pid==0){

printf(“I am child.\n”);

exit (0); o processo filho termina aqui

} else {

printf(“I am parent. My child pid is [%d]\n”, pid);

wait(NULL); espera o filho aqui

while(1);

}

return 0;

}

# ./zombie2

I am parent. My child pid is [2982]

I am child.

Saída do ps -ax

2981 pts/0 R+ 0:04 ./zombie2

Page 32: Linguagem de Programação IV

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>

int main(void){ pid_t child_pid, wpid; int status = 0; int i; int a[3] = {1, 2, 1};

printf("parent_pid = %d\n", getpid()); for (i = 0; i < 3; i++) { printf("i = %d\n", i); if ((child_pid = fork()) == 0) { printf("In child process (pid = %d)\n", getpid()); if (a[i] < 2) { printf("Should be accept\n"); exit(1); } else{ printf("Should be reject\n"); exit(0); } /*NOTREACHED*/ } } while ((wpid = wait(&status)) > 0) { printf("Exit status of %d was %d (%s)\n", (int)wpid, status, (status > 0) ? "accept" : "reject"); } return 0;}

Saída:

parent_pid = 15820i = 0i = 1In child process (pid = 15821)Should be accepti = 2In child process (pid = 15822)Should be rejectIn child process (pid = 15823)Should be acceptExit status of 15823 was 256 (accept)Exit status of 15822 was 0 (reject)Exit status of 15821 was 256 (accept)

Page 33: Linguagem de Programação IV

Criando dados compartilhados - IPC

Page 34: Linguagem de Programação IV

shmget vs mmap

Page 35: Linguagem de Programação IV

Bibliografia

Operating Systems, 4th Ed, William Stallings, Prentice Hall

Advanced Programming in the UNIX Environment, W. R.

Stevens, Addison-Wesley

Programming with GNU Software, M. Loukides e A. Oram,

O'Reilly

Managing Projects with make, A. Oram e S. Talbott, O'Reilly