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
Usando a família de chamadas de sistemas exec…(…)
exec, execl, execv, execve, …
exec…() troca o processo corrente pelo novo que foi
especificado
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
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[]);
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.
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
Exec
Propriedades
O novo programa herda do processo que o invoca
Process ID e parent process ID
Real user ID and real group ID
Supplementary group IDs
Process group ID
Session ID
Controlling terminal
Time left until alarm clock
Current working directory
Root directory
File mode creation mask
File locks
Process signal mask
Resource limits
tms_utime, tms_stime, tms_cutime and tms ustime values
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
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;
}
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
Fork
Processo 1
Processo 1
PAI
fork
FILHO
Processo 2
shell
shell
shell
fork
shell
exec
ps
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á
Exemplo de fork
#include < stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
if (fork()==0) {
printf(“Eu sou o filho\n”);
Cria o processo filho
Código executado pelo filho
} else {
printf(“Eu sou o pai\n”);
}
}
Código executado pelo pai
Comportamento fork
Comportamento do fork
Sequencia fork() + execve()
Fork vs Execve()
O que acontece com o processo filho quando
ele morre antes que o pai?
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
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
Exemplo de zombie
# ./zombie
I am parent. I loop here. My child pid is [2966]
#include <stdio.h>
#include <stdlib.h>
int main(){
int pid;
pid = fork();
I am child. I become a zombie now.
Saída do ps -ax
2965 pts/0
2966 pts/0
Z+
R+
0:24 ./zombie
0:00 [zombie] <defunct>
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;
}
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.
Esperar pela terminação
Chamado também
de join
Wait: cenários possíveis
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.
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.
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.
Exemplo
St é um ponteiro global
que recebe o retorno de
wait
Exemplo
Exemplo
# ./zombie2
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(){
int pid;
I am parent. My child pid is [2982]
I am child.
Saída do ps -ax
2981 pts/0
R+
0:04 ./zombie2
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;
}
#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 = 15820
i=0
i=1
In child process (pid = 15821)
Should be accept
i=2
In child process (pid = 15822)
Should be reject
In child process (pid = 15823)
Should be accept
Exit status of 15823 was 256 (accept)
Exit status of 15822 was 0 (reject)
Exit status of 15821 was 256 (accept)
Criando dados compartilhados - IPC
shmget
vs
mmap
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
Download

include