Chamada do sistema Exec Linux

Chamada do sistema Exec Linux
A chamada do sistema EXEC é usada para executar um arquivo que reside em um processo ativo. Quando o EXEC é chamado, o arquivo executável anterior é substituído e o novo arquivo é executado.

Mais precisamente, podemos dizer que o uso da chamada do sistema EXEC substituirá o arquivo ou programa antigo do processo por um novo arquivo ou programa. Todo o conteúdo do processo é substituído por um novo programa.

O segmento de dados do usuário que executa a chamada do sistema EXEC () é substituída pelo arquivo de dados cujo nome é fornecido no argumento enquanto chama Exec ().

O novo programa é carregado no mesmo espaço de processo. O processo atual é apenas transformado em um novo processo e, portanto, o ID do processo não é alterado, isso ocorre porque não estamos criando um novo processo, estamos apenas substituindo um processo por outro processo no executivo.

Se o processo atualmente em execução contiver mais de um thread, todos os threads serão encerrados e a nova imagem do processo será carregada e executada. Não há funções de destruidores que encerram fios do processo atual.

O PID do processo não é alterado, mas os dados, código, pilha, heap, etc. do processo são alterados e são substituídos pelos do processo recém -carregado. O novo processo é executado a partir do ponto de entrada.

O Exec System Call é uma coleção de funções e, na linguagem de programação C, os nomes padrão para essas funções são os seguintes:

  1. execl
  2. execle
  3. execlp
  4. EXECV
  5. execve
  6. EXECVP


Deve -se notar aqui que essas funções têm a mesma base exec seguido de uma ou mais letras. Estes são explicados abaixo:

e: É uma variedade de indicadores que aponta para variáveis ​​ambientais e é passada explicitamente para o processo recém -carregado.

eu: l é para os argumentos da linha de comando que passaram uma lista para a função

P: P é a variável de ambiente do caminho que ajuda a encontrar o arquivo passado como um argumento a ser carregado em processo.

v: v é para os argumentos da linha de comando. Estes são passados ​​como uma variedade de ponteiros para a função.

Por que o EXEC é usado?

Exec é usado quando o usuário deseja iniciar um novo arquivo ou programa no mesmo processo.

Trabalho interno do executivo

Considere os seguintes pontos para entender o funcionamento do executivo:

  1. A imagem atual do processo é substituída com uma nova imagem de processo.
  2. Nova imagem do processo é a que você passou como argumento executivo
  3. O processo atualmente em execução termina
  4. A nova imagem do processo tem o mesmo ID do processo, o mesmo ambiente e o mesmo descritor de arquivos (porque o processo não é substituído, a imagem do processo é substituída)
  5. A estatística da CPU e a memória virtual são afetadas. O mapeamento de memória virtual da imagem atual do processo é substituído pela memória virtual da nova imagem do processo.

Sintaxe das funções da família Exec:

A seguir, são apresentadas as sintaxes para cada função do EXEC:

int execl (const char* caminho, const char* arg,…)
int Execlp (Arquivo const char*, const char* arg,…)
int execle (const char* caminho, const char* arg,…, char* const Envp [])
int Execv (Const Char* Path, const char* argv [])
int Execvp (arquivo const char*, const char* argv [])
int ExecvPe (Arquivo const char*, const char* argv [], char* const Envp [])

Descrição:

O tipo de retorno dessas funções é int. Quando a imagem do processo é substituída com sucesso, nada é retornado à função de chamada porque o processo que a chamou não está mais em execução. Mas se houver algum erro -1 será devolvido. Se ocorrer algum erro um errno está definido.

Na sintaxe:

  1. caminho é usado para especificar o nome do caminho completo do arquivo que deve ser executado.
  1. Arg O argumento é aprovado. Na verdade, é o nome do arquivo que será executado no processo. Na maioria das vezes, o valor de arg e caminho é o mesmo.
  1. const char* arg nas funções Execl (), Execlp () e Execle () é considerado como arg0, arg1, arg2,…, argn. É basicamente uma lista de ponteiros para strings terminados nulos. Aqui, o primeiro argumento aponta para o nome do arquivo que será executado como descrito no ponto 2.
  1. Envp é uma matriz que contém ponteiros que apontam para as variáveis ​​de ambiente.
  1. arquivo é usado para especificar o nome do caminho que identificará o caminho do novo arquivo de imagem do processo.
  1. As funções do executivo chamam esse fim e são usados ​​para mudar o ambiente para a nova imagem do processo. Essas funções passam na lista de configurações de ambiente usando o argumento Envp. Este argumento é uma matriz de caracteres que aponta para a string null terminada e define a variável de ambiente.

Para usar as funções da família EXEC, você precisa incluir o seguinte arquivo de cabeçalho em seu programa C:

#incluir

Exemplo 1: Usando o programa Exec System Call in C

Considere o exemplo a seguir, no qual usamos o sistema EXEC Chamada na programação C em Linux, Ubuntu: temos dois arquivos C aqui Exemplo.c e olá.C:

exemplo.c

CÓDIGO:

#incluir
#incluir
#incluir
int main (int argc, char *argv [])

printf ("pid de exemplo.c = %d \ n ", getpid ());
char *args [] = "hello", "c", "programação", null;
EXECV ("./olá ", args);
printf ("de volta ao exemplo.C ");
retornar 0;

olá.c

CÓDIGO:

#incluir
#incluir
#incluir
int main (int argc, char *argv [])

printf ("Estamos em olá.C \ n ");
printf ("pid de olá.c = %d \ n ", getpid ());
retornar 0;

SAÍDA:

Pid de exemplo.c = 4733
Estamos em olá.c
Pid de olá.c = 4733

No exemplo acima, temos um exemplo.Arquivo C e olá.Arquivo C. No exemplo .C FILE ADIMENTO DE COMPLETO QUE PRIMOS O ID do processo atual (exemplo de arquivo.C está sendo executado no processo atual). Então, na próxima linha, criamos uma variedade de ponteiros de personagem. O último elemento desta matriz deve ser nulo como o ponto de rescisão.

Em seguida, usamos a função Execv () que leva o nome do arquivo e a matriz de ponteiro do personagem como seu argumento. Deve -se notar aqui que usamos ./ Com o nome do arquivo, ele especifica o caminho do arquivo. Como o arquivo está na pasta onde o exemplo.C reside para que não há necessidade de especificar o caminho completo.

Quando a função Execv () é chamada, nossa imagem de processo será substituída agora o exemplo do arquivo.c não está no processo, mas o arquivo olá.C está em processo. Pode -se observar que o ID do processo é o mesmo se olá.c é imagem ou exemplo de processo.C é a imagem do processo porque o processo é o mesmo e a imagem do processo é substituída apenas.

Então temos outra coisa a observar aqui, que é a instrução printf () após o Execv () não é executado. Isso ocorre porque o controle nunca é devolvido à imagem antiga do processo depois que a nova imagem do processo substitui -a. O controle só volta à função de chamada ao substituir a imagem do processo não tem sucesso. (O valor de retorno é -1 neste caso).

Diferença entre as chamadas do sistema Fork () e EXEC ():

A chamada do sistema Fork () é usada para criar uma cópia exata de um processo em execução e a cópia criada é o processo infantil e o processo de execução é o processo pai. Considerando que a chamada do sistema EXEC () é usada para substituir uma imagem de processo por uma nova imagem de processo. Portanto, não há conceito de processos de pais e filhos na chamada do sistema EXEC ().

No sistema Fork () chamam os processos pai e filho são executados ao mesmo tempo. Mas na chamada do sistema EXEC (), se a substituição da imagem do processo for bem -sucedida, o controle não retornará para onde a função EXEC foi chamada, em vez de executar o novo processo. O controle só será transferido de volta se houver algum erro.

Exemplo 2: Combinando as chamadas do Fork () e Exec ()

Considere o exemplo a seguir, no qual usamos as chamadas do sistema Fork () e EXEC () no mesmo programa:

exemplo.c

CÓDIGO:

#incluir
#incluir
#incluir
int main (int argc, char *argv [])

printf ("pid de exemplo.c = %d \ n ", getpid ());
pid_t p;
p = fork ();
if (p ==-1)

printf ("Há um erro ao chamar o fork ()");

if (p == 0)

printf ("Estamos no processo infantil \ n");
printf ("chamando olá.C do processo infantil \ n ");
char *args [] = "hello", "c", "programação", null;
EXECV ("./olá ", args);

outro

printf ("Estamos no processo pai");

retornar 0;

olá.C:

CÓDIGO:

#incluir
#incluir
#incluir
int main (int argc, char *argv [])

printf ("Estamos em olá.C \ n ");
printf ("pid de olá.c = %d \ n ", getpid ());
retornar 0;

SAÍDA:

Pid de exemplo.c = 4790
Estamos em processo pai
Estamos em processo infantil
Chamando olá.C do processo infantil
Estamos em olá.c
Pid de olá.c = 4791

Neste exemplo, usamos a chamada do sistema Fork (). Quando o processo infantil for criado 0 será atribuído a P e depois mudaremos para o processo infantil. Agora o bloco de declarações com se (p == 0) será executado. Uma mensagem é exibida e usamos a chamada do sistema EXECV () e a imagem atual do processo filho, que é o exemplo.c será substituído por olá.c. Antes de Execv (), ligue para os processos infantis e pais eram iguais.

Pode -se ver que o pid de exemplo.c e olá.C é diferente agora. Isso é porque exemplo.C é a imagem do processo pai e olá.C é a imagem do processo infantil.