Chamadas de sistema

Linux Exec System Call

Linux Exec System Call

A chamada de sistema exec é usada para executar um arquivo que está residindo em um processo ativo. Quando exec é chamado, o arquivo executável anterior é substituído e um novo arquivo é executado.

Mais precisamente, podemos dizer que usar a chamada de 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 de sistema exec () é substituído pelo arquivo de dados cujo nome é fornecido no argumento ao chamar exec ().

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

Se o processo atualmente em execução contiver mais de uma thread, todas as threads serão encerradas e a nova imagem do processo será carregada e executada. Não há funções destruidoras que encerram threads do processo atual.

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

A chamada do sistema Exec é 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. execvo
  6. execvp


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

e: É uma matriz de ponteiros que aponta para variáveis ​​de ambiente e é passada explicitamente para o processo recém-carregado.

eu: l é para os argumentos de linha de comando passados ​​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 no processo.

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

Por que exec é usado?

exec é usado quando o usuário deseja lançar 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 do processo atual é substituída por uma nova imagem do processo.
  2. A nova imagem do processo é aquela que você passou como argumento exec
  3. O processo atualmente em execução foi encerrado
  4. A nova imagem de processo tem o mesmo ID de processo, mesmo ambiente e mesmo descritor de arquivo (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 da memória virtual da imagem do processo atual é substituído pela memória virtual da nova imagem do processo.

Sintaxes das funções da família exec:

A seguir estão as sintaxes para cada função de exec:

int execl (const char * path, const char * arg, ...)
int execlp (arquivo const char *, const char * arg,…)
int execle (const char * path, const char * arg,…, char * const envp [])
int execv (const char * path, const char * argv [])
int execvp (arquivo const char *, const char * argv [])
int execvpe (const char * arquivo, 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 para a função de chamada porque o processo que o chamou não está mais em execução. Mas se houver algum erro -1 será retornado. 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 foi 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 terminadas em nulos. Aqui, o primeiro argumento aponta para o nome do arquivo que será executado conforme descrito no ponto 2.
  1. envp é um array que contém ponteiros que apontam para as variáveis ​​de ambiente.
  1. Arquivo é usado para especificar o nome do caminho que irá identificar o caminho do novo arquivo de imagem do processo.
  1. As funções de exec chamam que terminam com e são usados ​​para mudar o ambiente para a nova imagem do processo. Essas funções passam a lista de configuração de ambiente usando o argumento envp. Este argumento é uma matriz de caracteres que aponta para uma string terminada em nulo 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 a chamada de sistema exec no programa C

Considere o seguinte exemplo no qual usamos a chamada de sistema exec em programação C no Linux, Ubuntu: Temos dois arquivos c aqui exemplo.ce 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 [] = "Olá", "C", "Programação", NULL;
execv ("./ hello ", args);
printf ("Voltar ao exemplo.c ");
return 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 ());
return 0;

RESULTADO:

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 .arquivo c primeiro imprimimos o ID do processo atual (exemplo de arquivo.c está sendo executado no processo atual). Então, na próxima linha, nós criamos uma matriz de ponteiros de caracteres. O último elemento desta matriz deve ser NULL como ponto final.

Então nós usamos a função execv () que leva o nome do arquivo e o array de ponteiro de caractere como seu argumento. Deve-se notar aqui que usamos ./ com o nome do arquivo, especifica o caminho do arquivo. Como o arquivo está na pasta onde exemplo.c reside, então não há necessidade de especificar o caminho completo.

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

Então temos outra coisa a notar aqui que é a instrução printf () depois que execv () não é executado. Isso ocorre porque o controle nunca é retornado à imagem do processo antigo, uma vez que a nova imagem do processo o substitui. O controle só volta a chamar a função quando a substituição da imagem do processo é malsucedida. (O valor de retorno é -1 neste caso).

Diferença entre chamadas de sistema fork () e exec ():

A chamada de sistema fork () é usada para criar uma cópia exata de um processo em execução e a cópia criada é o processo filho e o processo em execução é o processo pai. Enquanto a chamada de sistema exec () é usada para substituir uma imagem de processo por uma nova imagem de processo. Portanto, não há conceito de processos pai e filho na chamada de sistema exec ().

Na chamada do sistema fork () 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 retorna para onde a função exec foi chamada, em vez disso, ele executará o novo processo. O controle só será transferido de volta se houver algum erro.

Exemplo 2: Combinando chamadas de sistema fork () e exec ()

Considere o exemplo a seguir, no qual usamos as chamadas de 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 = garfo ();
if (p == - 1)

printf ("Ocorreu um erro ao chamar fork ()");

if (p == 0)

printf ("Estamos no processo filho \ n");
printf ("Chamando oi.c do processo filho \ n ");
char * args [] = "Olá", "C", "Programação", NULL;
execv ("./ hello ", args);

senão

printf ("Estamos no processo pai");

return 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 ());
return 0;

RESULTADO:

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

Neste exemplo, usamos a chamada de sistema fork (). Quando o processo filho for criado, 0 será atribuído a p e então passaremos para o processo filho. Agora o bloco de instruções com if (p == 0) será executado. Uma mensagem é exibida e nós usamos a chamada de sistema execv () e a imagem do processo filho atual que é um exemplo.c será substituído por olá.c. Antes da chamada de execv (), os processos filho e pai eram os mesmos.

Pode ser visto que o PID de exemplo.ce olá.c é diferente agora. Isso ocorre porque exemplo.c é a imagem do processo pai e olá.c é a imagem do processo filho.

5 melhores jogos de arcade para Linux
Hoje em dia, os computadores são máquinas sérias usadas para jogos. Se você não pode obter a nova pontuação máxima, você saberá o que quero dizer. Nes...
Batalha por Wesnoth 1.13.6 Desenvolvimento lançado
Batalha por Wesnoth 1.13.6 lançado no mês passado, é o sexto lançamento de desenvolvimento no 1.13.série x e oferece uma série de melhorias, principal...
Como instalar o League Of Legends no Ubuntu 14.04
Se você é fã de League of Legends, esta é uma oportunidade para testar o funcionamento de League of Legends. Observe que LOL é suportado no PlayOnLinu...