Sobreposição de imagem de processo

Suponha que estamos executando um programa e queremos executar outro programa a partir do programa atual. Isso é possível? Por que não, se implementarmos o conceito de sobreposição da imagem do processo. Tudo bem, mas e o programa em execução no momento, ele também pode ser executado. Como é possível, já que sobrepomos o programa atual com o novo programa. O que fazer, se quiser executar os dois programas sem perder o programa em execução no momento, é possível? Sim, é possível.

Crie um processo filho, para que tenhamos um processo pai e um processo filho recém-criado. Já estamos executando o programa atual no processo pai, então execute o processo recém-criado no filho. Desta forma, podemos executar outro programa a partir do programa atual. Não apenas um único programa, mas podemos executar qualquer número de programas a partir do programa atual, criando esse número de processos filho.

Vamos considerar o seguinte programa como exemplo.

/ * Nome do arquivo: helloworld.c * /

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

/ * Nome do arquivo: execl_test.c * /

#include<stdio.h>
#include<unistd.h>

void main() {
   execl("./helloworld", "./helloworld", (char *)0);
   printf("This wouldn't print\n");
   return;
}

O programa acima iria sobrepor a imagem do processo de execl_test com helloworld. Essa é a razão, o código da imagem do processo de execl_test (printf ()) não é executado.

Etapas de compilação e execução

Hello World

Agora, executaremos os dois programas a seguir a partir de um programa, ou seja, execl_run_two_prgms.c.

  • Programa Hello World (helloworld.c)

  • Programa de loop while para imprimir de 1 a 10 (while_loop.c)

/ * Nome do arquivo: while_loop.c * /

/* Prints numbers from 1 to 10 using while loop */
#include<stdio.h>

void main() {
   int value = 1;
   while (value <= 10) {
      printf("%d\t", value);
      value++;
   }
   printf("\n");
   return;
}

A seguir está o programa para executar dois programas (um programa do filho e outro programa do pai).

/ * Nome do arquivo: execl_run_two_prgms.c * /

#include<stdio.h>
#include<unistd.h>

void main() {
   int pid;
   pid = fork();
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      execl("./helloworld", "./helloworld", (char *)0);
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

Note - Faça a chamada sleep () para garantir que os processos filho e pai sejam executados sequencialmente (não sobreponha o resultado).

Etapas de compilação e execução

Child process: Running Hello World Program
This wouldn't print
Parent process: Running While loop Program
Won't reach here

Agora, executaríamos dois programas de um programa, ou seja, execl_run_two_prgms.c, o mesmo programa acima, mas com argumentos de linha de comando. Portanto, estamos executando dois programas, a saber, helloworld.c no processo filho e o programa while_loop.c no processo pai. É o seguinte -

  • Programa Hello World (helloworld.c)

  • Programa de loop while para imprimir de 1 a num_times_str de acordo com os argumentos da linha de comando (while_loop.c)

Este programa executa amplamente as seguintes ações -

  • Cria um processo filho

  • O processo filho executa o programa helloworld.c

  • O processo pai executa o programa while_loop.c, passando o valor do argumento da linha de comando como um argumento para o programa. Se os argumentos da linha de comando não forem passados, o padrão será considerado 10. Caso contrário, ele receberá o valor do argumento fornecido. O valor do argumento deve ser numérico; o código não seria validado se fornecido em alfabetos.

/ * Nome do arquivo: execl_run_two_prgms.c * /

#include<stdio.h>
#include<string.h>
#include<unistd.h>

void main(int argc, char *argv[0]) {
   int pid;
   int err;
   int num_times;
   char num_times_str[5];
   
   /* In no command line arguments are passed, then loop maximum count taken as 10 */
   if (argc == 1) {
      printf("Taken loop maximum as 10\n");
      num_times = 10;
      sprintf(num_times_str, "%d", num_times);
   } else {
      strcpy(num_times_str, argv[1]);
      printf("num_times_str is %s\n", num_times_str);
      pid = fork();
   }
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      err = execl("./helloworld", "./helloworld", (char *)0);
      printf("Error %d\n", err);
      perror("Execl error: ");
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)num_times_str, (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

A seguir está o programa helloworld.c chamado a partir do processo filho do programa, execl_run_two_prgms.c.

/ * Nome do arquivo: helloworld.c * /

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

A seguir está o programa while_loop.c chamado do processo pai do programa, execl_run_two_prgms.c. O argumento para este programa é passado do programa que o executa, isto é, execl_run_two_prgms.c.

/ * Nome do arquivo: while_loop.c * /

#include<stdio.h>

void main(int argc, char *argv[]) {
   int start_value = 1;
   int end_value;
   if (argc == 1)
   end_value = 10;
   else
   end_value = atoi(argv[1]);
   printf("Argv[1] is %s\n", argv[1]);
   while (start_value <= end_value) {
      printf("%d\t", start_value);
      start_value++;
   }
   printf("\n");
   return;
}

Etapas de compilação e execução

Taken loop maximum as 10
num_times_str is 10
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 10
1 2 3 4 5 6 7 8 9 10
Taken loop maximum as 15
num_times_str is 15
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Vamos agora ver as funções de biblioteca relacionadas com imagens de sobreposição.

#include<unistd.h>

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

Esta função sobrepõe a imagem do processo em execução atual com o novo processo, conforme mencionado nos argumentos, caminho e arg. Se algum argumento precisar ser passado para uma nova imagem de processo, isso será enviado por meio de argumentos “arg” e o último argumento deve ser NULL.

Esta função retornaria um valor apenas em caso de erro. As chamadas relacionadas ao processo de sobreposição de imagens são mencionadas abaixo -

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

Essas chamadas abordariam a passagem de argumentos de linha de comando (argv []), variáveis ​​de ambiente (envp []) e outros parâmetros.